jonnifyelixir
F6 / F6.02 / pipelines

F6.02 · part 2 of 3

Pipelines & scopes

Some work has to happen on the way to almost every action — fetch the session, reject a forged form, set security headers, require a logged-in user. A pipeline is how you name that work once: an ordered stack of plugs given a name like :browser or :api. A scope then runs a group of routes through one or more pipelines with pipe_through, so the cross-cutting steps are declared in a single place rather than copied into every controller. Stack pipelines and a route can require both the browser basics and authentication before it is ever reached — and the action stays as thin as it was in F6.01.

See three common pipelines, how scopes route groups of paths through them, then the router that declares them. Auth is not special — it is one more pipeline.

Three pipelines

A pipeline groups the plugs a class of request needs. Browser pages need a session and CSRF protection; a JSON API needs none of that but must accept JSON; a protected area needs the user loaded and checked. Select a pipeline to see what it runs.

Pipelines · select one

:browser fetch_session · fetch_live_flash · protect_from_forgery · headers HTML pages :api accepts ["json"] — no session, no CSRF JSON clients :require_auth RequireUser — load the user, halt if missing (F6.02.3) protected area

pipeline: :browser

runs: session, CSRF, headers

Name the work, not the repetition. A pipeline is the difference between “every action remembers to check auth” and “these routes go through :require_auth” — the second cannot be forgotten.

Scopes route through pipelines

A scope is a group of routes with a shared path prefix and a pipe_through. Public pages run through :browser; a protected dashboard stacks :browser and :require_auth; the API runs through :api. Same routes, different plugs in front.

Three scopes, three pipe_through choices

scope "/" pipe_through :browser get /courses get /courses/:id post /enroll scope "/dashboard" :browser, :require_auth live / DashboardLive user loaded & checked before any route scope "/api" pipe_through :api get /courses/:id JSON in / JSON out no session

Scopes are how one app serves a browser and an API without tangling them: the routes can even share a path, because the pipeline in front decides what kind of request each scope expects.

The router

Pipelines are declared once at the top; scopes pipe groups of routes through them. Stacking [:browser, :require_auth] runs the browser plugs and then the auth plug before the dashboard’s routes — the RequireUser plug is the one we write next.

pipeline :browser do
  plug :fetch_session
  plug :fetch_live_flash
  plug :protect_from_forgery
  plug :put_secure_browser_headers
end

pipeline :require_auth do
  plug PortalWeb.RequireUser         # a plug we write in F6.02.3
end

scope "/", PortalWeb do
  pipe_through :browser
  get "/courses/:id", CourseController, :show
end

scope "/dashboard", PortalWeb do
  pipe_through [:browser, :require_auth]   # stack pipelines
  live "/", DashboardLive
end

name the work

A pipeline is an ordered stack of plugs with a name — declared once.

route groups through it

pipe_through runs a scope’s routes through the chosen pipelines.

Next: writing a plug — the RequireUser plug the :require_auth pipeline runs, and the contract every plug shares.

References

Primary sources for this lesson, and where it connects in the course.

Sources

Related in this course