I have a simple Plug router that has some POST, PUT and GET endpoints. However, each endpoint needs to make a specific validation on the headers of the request. I don’t know how to achieve this with Plug. Code
I have a very generic router that receives requests and redirects them to controllers:
defmodule Api do
use Plug.Router
alias Api.Controllers.{Product, NotFound, Ping}
plug :match
plug Plug.Logger
plug :dispatch
get "/ping", do: Ping.process(conn)
put "/product", do: Product.process(conn)
match _, do: NotFound.process(conn)
end
However, there is a step missing. I need for the /products endpoint to validate the headers. Namely the headers should have some specific fields set, for example, like the “conten-type” header or even a custom header like “bananas”.
This validation is NOT for all endpoints. What makes it worse is that each endpoint will make its own validations, for example, having a “bananas” header may be important for the “/products” endpoint, but the “/ping” endpoint doesn’t really care.
I have read this article:
However, this applies to all endpoints and is not specific.
You can do anything you want in the do
block for the paths in plug. I sometimes use an around filter pattern for things like this. Something like:
defmodule Api do
use Plug.Router
# ...
put "/product" do
with_valid_headers(conn, fn ->
Product.process(conn)
end)
end
defp with_valid_headers(conn, action) do
if get_req_header(conn, "banana") == "Cavendish" do
action.()
else
send_resp(conn, 400, "Invalid banana")
end
end
# ...
end
Of course, if this validation is not going to be reused, you can just place it in the body of the do
block.