Phoenix.Controller.Pipeline

This module implements the controller pipeline responsible for handling requests.

The pipeline

The goal of a controller is to receive a request and invoke the desired action. The whole flow of the controller is managed by single pipeline:

defmodule UserController do
  use Phoenix.Controller
  require Logger

  plug :log_message, "before action"
  plug :action
  plug :log_message, "after action"

  def show(conn, _params) do
    Logger.debug "show/2"
    send_resp(conn, 200, "OK")
  end

  defp log_message(conn, msg) do
    Logger.debug msg
    conn
  end
end

When invoked, this pipeline will print:

before action
show/2
after action

As any other Plug pipeline, we can halt at any step by calling Plug.Conn.halt/1 (which is by default imported into controllers). If we change log_message/2 to:

def log_message(conn, msg) do
  Logger.debug msg
  halt(conn)
end

it will print only:

before action

As the rest of the pipeline (the action and the after action plug) will never be invoked.

Guards

plug/2 support guards, allowing a developer to configure a plug to only run in some particular action:

plug :log_message, "before action" when action in [:show, :edit]
plug :action
plug :log_message, "after action" when not action in [:index]

The first plug will run only when action is show and edit, while the second will always run except for the index action.

Those guards work like regular Elixir guards and the only variables accessible in the guard are conn, the action as an atom and the controller as an alias.

Controllers are plugs

Like routers, controllers are plugs, but they are wired to dispatch to a particular function which is called an action.

For example, the route:

get "/users/:id", UserController, :show

will invoke UserController as a plug:

UserController.call(conn, :show)

which will trigger the plug pipeline and which will eventually invoke the inner action plug that dispatches to the show/2 function in the UserController.

As controllers are plugs, they implement both init/1 and call/2, and it also provides a function named action/2 which is responsible for dispatching the appropriate action in the middle of the plug stack (and is also overridable).

Source

Summary

plug(plug)

Stores a plug to be executed as part of the plug pipeline

plug(plug, opts)

Stores a plug with the given options to be executed as part of the plug pipeline

Macros

plug(plug)

Stores a plug to be executed as part of the plug pipeline.

Source
plug(plug, opts)

Stores a plug with the given options to be executed as part of the plug pipeline.

Source