背景
我有一个简单的Plug路由器,它有一些POST、PUT和GET端点。但是,每个端点都需要对请求的头进行特定的验证。我不知道如何用Plug实现这一点。代码
我有一个非常通用的路由器,可以接收请求并将其重定向到控制器:
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
问题
然而,还缺少一个步骤。我需要/products端点来验证标头。也就是说,标头应该设置一些特定的字段,例如,像"content-type"标头,甚至像"香蕉"这样的自定义标头。
此验证不适用于所有终结点。更糟糕的是,每个端点都会进行自己的验证,例如,对于"/products"端点来说,拥有一个"香蕉"头可能很重要,但"/ping"端点并不在乎。
研究
我读过这篇文章:
- https://www.adamconrad.dev/blog/verifying-request-signatures-in-elixir-phoenix/
但是,这适用于所有端点,并且不是特定的。
问题
- 有可能用Plug实现我想要的目标吗?如果是,如何
您可以在do
块中为plug中的路径执行任何您想要的操作。对于这样的事情,我有时会使用环绕过滤模式。类似于:
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
当然,如果这个验证不被重用,您可以将它放在do
块的主体中。