Action-Specific Plug Pipelines for Phoenix
Feb 13, 2020
For our APIs, most of our actions need a common set of plugs (Elixir's middleware). Phoenix has the concept of pipelines, which are a sequence of plugs you can apply to a group of routes. But our actions tend to need action-specific configuraiton.
The way to do this in Phoenix is via the plug
macro with a guard clause on your aciton:
plug App.Plugs.Context, [route: "user_list"] when action == :index
plug App.Plugs.Cache, [:public, ttl: 60] when action == :index
plug App.Plugs.Validate, [
search: [string: [max: 50]],
page: [:int, default: 1]
] when action == :index
It's a mouthful! But with a bit of code, we can turn the above into:
pipeline :index, [
context: [route: "user_list"],
cache: [:public, ttl: 60],
validate: [
search: [string: [max: 50]],
page: [:int, default: 1]
]
]
pipeline/2
is just a macro that converts this improved version into the original:
defmacro pipeline(action, plugs) do
for {plug, config} <- plugs do
plug = case plug do
:context -> App.Plugs.Context
:cache -> App.Plugs.Cache
:validate -> App.Plugs.Validate
end
quote location: :keep do
plug unquote(plug), unquote(config) when var!(action) == unquote(action)
end
end
end
I hope someone finds that useful.