使用 Plug 验证特定端点的 headers
Validating headers for specific endpoints with Plug
背景
我有一个简单的 Plug 路由器,它有一些 POST、PUT 和 GET 端点。但是,每个端点都需要对请求的 header 进行特定的验证。我不知道如何用 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 端点来验证 headers。也就是说,headers 应该设置一些特定的字段,例如,像“conten-type”header 甚至是自定义的 header,如“bananas”。
此验证不适用于所有端点。更糟糕的是,每个端点都会进行自己的验证,例如,拥有“bananas”header 可能对“/products”端点很重要,但“/ping”端点并不关心.
研究
我已阅读这篇文章:
但是,这适用于所有端点,并不具体。
问题
- 是否可以通过 Plug 实现我想要的功能?如果是,怎么做?
您可以在 do
块中为插件中的路径做任何您想做的事情。我有时会使用环绕过滤模式来处理这样的事情。类似于:
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
块的主体中。
背景
我有一个简单的 Plug 路由器,它有一些 POST、PUT 和 GET 端点。但是,每个端点都需要对请求的 header 进行特定的验证。我不知道如何用 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 端点来验证 headers。也就是说,headers 应该设置一些特定的字段,例如,像“conten-type”header 甚至是自定义的 header,如“bananas”。
此验证不适用于所有端点。更糟糕的是,每个端点都会进行自己的验证,例如,拥有“bananas”header 可能对“/products”端点很重要,但“/ping”端点并不关心.
研究
我已阅读这篇文章:
但是,这适用于所有端点,并不具体。
问题
- 是否可以通过 Plug 实现我想要的功能?如果是,怎么做?
您可以在 do
块中为插件中的路径做任何您想做的事情。我有时会使用环绕过滤模式来处理这样的事情。类似于:
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
块的主体中。