Plug 路由器是否需要 match/dispatch 管道?
Does a Plug router need a match/dispatch pipeline?
我有一个路由器模块,可以将请求转发到其他路由器。
在这个路由器中,我有一个由 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
在第二个模块中,我有相同的管道:
defmodule Example.Route.Check do
use Plug.Router
plug(:match)
plug(:dispatch)
get "/", do: send_resp(conn, 200, "ok")
end
我在这里看到的问题是,在所有 Plug
路由器中,我似乎总是需要 plug(:match)
和 plug(:dispatch)
。所以我有以下问题:
- 这真的有必要吗?
- 是否所有路由器都需要在具有路由的同一文件中包含管道?
是的,两个插头总是需要的:
这里明显的问题是:
Why not just do it automatically, since this needs to be done for every request?
对于初学者来说,这是因为elixir有一种设计理念,即显式而不是隐式 ].
其次,更重要的是,插件按照定义的顺序执行。这使开发人员可以完全控制传入请求的处理方式。
例如,您可能希望在路由匹配之前检查 Authorization
header 并从那里停止或继续请求。或者您可能希望在一个单独的过程中更新页面浏览量,一旦路由匹配但在处理之前。另一种常见的情况是parse a JSON request在一条路由被匹配后
您可以通过自定义管道来完成所有这些以及更多操作:
defmodule Example.Router do
use Plug.Router
plug(CheckRateLimit)
plug(VerifyAuthHeader)
plug(:match)
plug(LogWebRequest)
plug(Plug.Parsers, parsers: [:json], ...)
plug(:dispatch)
# ...
end
将匹配的路由转发到其他路由器的能力可以使您的网络服务器更加复杂。例如,您可以检查基本路由器中的 API 速率限制,将 /admin
路由转发到单独的 AuthorizedRouter
并在匹配这些路由之前将自定义 VerifyAuthHeader
插头放在那里.
虽然@Sheharyar 的回答是绝对正确的,但我想补充一点,您可能会通过引入自己的辅助宏来干:
defmodule Example.Route.Common do
defmacro __using__(opts \ []) do
quote do
use Plug.Router
plug(:match)
plug(:dispatch)
end
end
end
并像这样使用它:
defmodule Example.Route.Check do
use Example.Route.Common
get "/", do: send_resp(conn, 200, "ok")
end
opts
参数可用于精细配置包含的插件。
我有一个路由器模块,可以将请求转发到其他路由器。
在这个路由器中,我有一个由 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
在第二个模块中,我有相同的管道:
defmodule Example.Route.Check do
use Plug.Router
plug(:match)
plug(:dispatch)
get "/", do: send_resp(conn, 200, "ok")
end
我在这里看到的问题是,在所有 Plug
路由器中,我似乎总是需要 plug(:match)
和 plug(:dispatch)
。所以我有以下问题:
- 这真的有必要吗?
- 是否所有路由器都需要在具有路由的同一文件中包含管道?
是的,两个插头总是需要的:
这里明显的问题是:
Why not just do it automatically, since this needs to be done for every request?
对于初学者来说,这是因为elixir有一种设计理念,即显式而不是隐式 ].
其次,更重要的是,插件按照定义的顺序执行。这使开发人员可以完全控制传入请求的处理方式。
例如,您可能希望在路由匹配之前检查 Authorization
header 并从那里停止或继续请求。或者您可能希望在一个单独的过程中更新页面浏览量,一旦路由匹配但在处理之前。另一种常见的情况是parse a JSON request在一条路由被匹配后
您可以通过自定义管道来完成所有这些以及更多操作:
defmodule Example.Router do
use Plug.Router
plug(CheckRateLimit)
plug(VerifyAuthHeader)
plug(:match)
plug(LogWebRequest)
plug(Plug.Parsers, parsers: [:json], ...)
plug(:dispatch)
# ...
end
将匹配的路由转发到其他路由器的能力可以使您的网络服务器更加复杂。例如,您可以检查基本路由器中的 API 速率限制,将 /admin
路由转发到单独的 AuthorizedRouter
并在匹配这些路由之前将自定义 VerifyAuthHeader
插头放在那里.
虽然@Sheharyar 的回答是绝对正确的,但我想补充一点,您可能会通过引入自己的辅助宏来干:
defmodule Example.Route.Common do
defmacro __using__(opts \ []) do
quote do
use Plug.Router
plug(:match)
plug(:dispatch)
end
end
end
并像这样使用它:
defmodule Example.Route.Check do
use Example.Route.Common
get "/", do: send_resp(conn, 200, "ok")
end
opts
参数可用于精细配置包含的插件。