我有一个路由器模块,可以将请求转发到其他路由器。在这个路由器中,我有一个由plug(:match)和组成的管道plug(:dispatch)。
defmodule Example.Router do
use Plug.Router
plug(:match)
plug(:dispatch)
forward("/check", to: Example.Route.Check)
get("/", do: send_resp(conn, 200, "router"))
end
Run Code Online (Sandbox Code Playgroud)
在第二个模块中,我有相同的管道:
defmodule Example.Route.Check do
use Plug.Router
plug(:match)
plug(:dispatch)
get "/", do: send_resp(conn, 200, "ok")
end
Run Code Online (Sandbox Code Playgroud)
我在这里看到的问题是我似乎总是需要plug(:match)并且plug(:dispatch)在所有Plug路由器中。所以我有以下问题:
Yes, both of the plugs are always required:
The :match plug is responsible for, well, matching the incoming request to one of the defined routes in the Router.
The :dispatch plug is responsible for finally processing the request in the matched route.
The obvious question here would be:
Why not just do it automatically, since this needs to be done for every request?
For starters, it's because elixir has a design philosophy of doing things explicitly instead of implicitly.
Second and more importantly, plugs are executed in the order they are defined. This gives the developer full control of how incoming requests are processed.
例如,您可能希望Authorization在匹配路由之前检查标头并从那里停止或继续请求。或者您可能希望在一个单独的过程中更新浏览量计数,一旦路由匹配但在处理之前。另一个常见的场景是在路由匹配后解析 JSON 请求 。
您可以通过自定义管道来完成所有这些以及更多操作:
defmodule Example.Router do
use Plug.Router
plug(CheckRateLimit)
plug(VerifyAuthHeader)
plug(:match)
plug(LogWebRequest)
plug(Plug.Parsers, parsers: [:json], ...)
plug(:dispatch)
# ...
end
Run Code Online (Sandbox Code Playgroud)
将匹配的路由转发到其他路由器的能力可以使您的 Web 服务器更加复杂。例如,您可以检查基本路由器中的 API 速率限制,将路由转发/admin到单独的AuthorizedRouter并VerifyAuthHeader在这些路由匹配之前在那里放置自定义插件。