查看源代码 路由
要求:本指南假设您已阅读过 请求生命周期指南。
路由器是 Phoenix 应用的主要枢纽。它们将 HTTP 请求匹配到控制器动作,连接实时通道处理程序,并定义一系列作用于一组路由的管道转换。
Phoenix 生成的路由器文件,lib/hello_web/router.ex
,看起来会像这样
defmodule HelloWeb.Router do
use HelloWeb, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {HelloWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
end
pipeline :api do
plug :accepts, ["json"]
end
scope "/", HelloWeb do
pipe_through :browser
get "/", PageController, :home
end
# Other scopes may use custom stacks.
# scope "/api", HelloWeb do
# pipe_through :api
# end
# ...
end
路由器和控制器模块名称都将以您为应用提供的名称作为前缀,后缀为 Web
。
该模块的第一行,use HelloWeb, :router
,只是在我们的特定路由器中提供 Phoenix 路由器功能。
作用域在本指南中拥有自己的部分,因此我们不会在这里花时间讨论 scope "/", HelloWeb do
块。 pipe_through :browser
行将在本指南的“管道”部分得到全面介绍。现在,您只需要知道管道允许将一组插头应用于不同的路由集。
然而,在作用域块内,我们有了第一个实际路由
get "/", PageController, :home
get
是一个 Phoenix 宏,对应于 HTTP 动词 GET。类似的宏存在于其他 HTTP 动词中,包括 POST、PUT、PATCH、DELETE、OPTIONS、CONNECT、TRACE 和 HEAD。
为什么使用宏?
Phoenix 尽力减少宏的使用。但是,您可能已经注意到,
Phoenix.Router
严重依赖于宏。为什么呢?我们使用
get
、post
、put
和delete
来定义您的路由。我们使用宏来实现两个目的
它们定义了路由引擎,用于每个请求,以选择将请求分派到哪个控制器。由于宏的存在,Phoenix 将所有路由编译成一个巨大的 case 语句,其中包含模式匹配规则,这些规则由 Erlang VM 高度优化。
对于您定义的每个路由,我们还定义元数据来实现
Phoenix.VerifiedRoutes
。正如我们很快就会了解到的,经过验证的路由允许我们像引用普通字符串一样引用任何路由,只是它经过编译器的验证以确保有效(从而使将损坏的链接、表单、邮件等发送到生产环境变得更加困难)。换句话说,路由器依赖于宏来构建速度更快、更安全的应用程序。还要记住,Elixir 中的宏只是编译时存在的,这在代码编译后提供了很多稳定性。正如我们将在下一节中学习到的,Phoenix 还通过
mix phx.routes
为所有定义的路由提供自省功能。
检查路由
Phoenix 提供了一个非常棒的工具来调查应用程序中的路由:mix phx.routes
。
让我们看看它是如何工作的。转到新生成的 Phoenix 应用程序的根目录并运行 mix phx.routes
。您应该看到类似以下内容,其中包含您当前拥有的所有路由
$ mix phx.routes
GET / HelloWeb.PageController :home
...
上面的路由告诉我们,任何针对应用程序根目录的 HTTP GET 请求都将由 HelloWeb.PageController
的 home
动作处理。
资源
除了像 get
、post
和 put
这样的 HTTP 动词宏外,路由器还支持其他宏。其中最重要的一个是 resources
。让我们将资源添加到 lib/hello_web/router.ex
文件中,如下所示
scope "/", HelloWeb do
pipe_through :browser
get "/", PageController, :home
resources "/users", UserController
...
end
现在,我们还没有实际的 HelloWeb.UserController
,这并不重要。
再次在项目根目录中运行 mix phx.routes
。您应该看到类似以下内容
...
GET /users HelloWeb.UserController :index
GET /users/:id/edit HelloWeb.UserController :edit
GET /users/new HelloWeb.UserController :new
GET /users/:id HelloWeb.UserController :show
POST /users HelloWeb.UserController :create
PATCH /users/:id HelloWeb.UserController :update
PUT /users/:id HelloWeb.UserController :update
DELETE /users/:id HelloWeb.UserController :delete
...
这是 HTTP 动词、路径和控制器动作的标准矩阵。有一段时间,这被称为 RESTful 路由,但现在大多数人认为这是一个误称。让我们分别看看它们。
- 发送到
/users
的 GET 请求将调用index
动作以显示所有用户。 - 发送到
/users/:id/edit
的 GET 请求将调用edit
动作,并带有一个 ID,从数据存储中检索单个用户,并将信息显示在用于编辑的表单中。 - 发送到
/users/new
的 GET 请求将调用new
动作,以显示一个用于创建新用户的表单。 - 发送到
/users/:id
的 GET 请求将调用show
动作,并带有一个 ID,以显示由该 ID 标识的单个用户。 - 发送到
/users
的 POST 请求将调用create
动作,以将新用户保存到数据存储中。 - 发送到
/users/:id
的 PATCH 请求将调用update
动作,并带有一个 ID,以将更新后的用户保存到数据存储中。 - 发送到
/users/:id
的 PUT 请求也将调用update
动作,并带有一个 ID,以将更新后的用户保存到数据存储中。 - 发送到
/users/:id
的 DELETE 请求将调用delete
动作,并带有一个 ID,以从数据存储中删除单个用户。
如果我们不需要所有这些路由,我们可以使用 :only
和 :except
选项选择性地过滤特定动作。
假设我们有一个只读的帖子资源。我们可以像这样定义它
resources "/posts", PostController, only: [:index, :show]
运行 mix phx.routes
显示我们现在只有定义了到 index 和 show 动作的路由。
GET /posts HelloWeb.PostController :index
GET /posts/:id HelloWeb.PostController :show
类似地,如果我们有一个评论资源,并且我们不想提供删除评论的路由,我们可以像这样定义路由。
resources "/comments", CommentController, except: [:delete]
现在运行 mix phx.routes
显示我们拥有除 DELETE 请求到 delete 动作以外的所有路由。
GET /comments HelloWeb.CommentController :index
GET /comments/:id/edit HelloWeb.CommentController :edit
GET /comments/new HelloWeb.CommentController :new
GET /comments/:id HelloWeb.CommentController :show
POST /comments HelloWeb.CommentController :create
PATCH /comments/:id HelloWeb.CommentController :update
PUT /comments/:id HelloWeb.CommentController :update
Phoenix.Router.resources/4
宏描述了用于自定义资源路由的其他选项。
经过验证的路由
Phoenix 包含 Phoenix.VerifiedRoutes
模块,该模块使用 ~p
符号对路由器路径与您的路由器进行编译时检查。例如,您可以在控制器、测试和模板中编写路径,编译器将确保这些路径与您的路由器中定义的路由实际匹配。
让我们看看它是如何工作的。在项目的根目录中运行 iex -S mix
。我们将定义一个临时示例模块,该模块构建一对 ~p
路由路径。
iex> defmodule RouteExample do
...> use HelloWeb, :verified_routes
...>
...> def example do
...> ~p"/comments"
...> ~p"/unknown/123"
...> end
...> end
warning: no route path for HelloWeb.Router matches "/unknown/123"
iex:5: RouteExample.example/0
{:module, RouteExample, ...}
iex>
请注意,对现有路由 ~p"/comments"
的第一次调用没有产生任何警告,但错误的路由路径 ~p"/unknown/123"
产生了编译器警告,正如预期的那样。这很重要,因为它允许我们编写应用程序中原本硬编码的路径,并且编译器会在我们编写错误的路由或更改路由结构时通知我们。
Phoenix 项目开箱即用地设置为允许在整个 Web 层(包括测试)中使用经过验证的路由。例如,在您的模板中,您可以渲染 ~p
链接
<.link href={~p"/"}>Welcome Page!</.link>
<.link href={~p"/comments"}>View Comments</.link>
或在控制器中发出重定向
redirect(conn, to: ~p"/comments/#{comment}")
对路由路径使用 ~p
可确保我们的应用程序路径和 URL 与路由器定义保持一致。编译器将为我们捕获错误,并在我们更改应用程序其他地方引用的路由时通知我们。
关于经过验证的路由的更多信息
查询字符串路径怎么办?您可以直接添加查询字符串键值对,或者提供键值对字典,例如
~p"/users/17?admin=true&active=false"
"/users/17?admin=true&active=false"
~p"/users/17?#{[admin: true]}"
"/users/17?admin=true"
如果我们需要完整的 URL 而不是路径怎么办?只需将您的路径用对 Phoenix.VerifiedRoutes.url/1
的调用包装起来,该调用在任何 ~p
可用的地方都被导入
url(~p"/users")
"http://localhost:4000/users"
url
调用将从为每个环境设置的配置参数中获取主机、端口、代理端口和 SSL 信息,以构造完整的 URL。我们将在专门的指南中详细讨论配置。现在,您可以查看项目中的 config/dev.exs
文件以查看这些值。
嵌套资源
也可以在 Phoenix 路由器中嵌套资源。假设我们还有一个 posts
资源,它与 users
存在多对一的关系。也就是说,一个用户可以创建多个帖子,而一个帖子只属于一个用户。我们可以通过在 lib/hello_web/router.ex
中添加一个嵌套路由来表示这一点,如下所示
resources "/users", UserController do
resources "/posts", PostController
end
当我们现在运行 mix phx.routes
时,除了上面我们看到的 users
路由外,我们还得到了以下路由集
...
GET /users/:user_id/posts HelloWeb.PostController :index
GET /users/:user_id/posts/:id/edit HelloWeb.PostController :edit
GET /users/:user_id/posts/new HelloWeb.PostController :new
GET /users/:user_id/posts/:id HelloWeb.PostController :show
POST /users/:user_id/posts HelloWeb.PostController :create
PATCH /users/:user_id/posts/:id HelloWeb.PostController :update
PUT /users/:user_id/posts/:id HelloWeb.PostController :update
DELETE /users/:user_id/posts/:id HelloWeb.PostController :delete
...
我们看到这些路由中的每一个都将帖子作用域到用户 ID。对于第一个,我们将调用 PostController
的 index
动作,但我们将传入 user_id
。这意味着我们将只显示该用户的全部帖子。相同的范围适用于所有这些路由。
构建嵌套路由的路径时,需要在路由定义中将 ID 插入到它们应该在的位置。对于以下 show
路由,42
是 user_id
,17
是 post_id
。
user_id = 42
post_id = 17
~p"/users/#{user_id}/posts/#{post_id}"
"/users/42/posts/17"
经过验证的路由也支持 Phoenix.Param
协议,但我们现在不需要关心 Elixir 协议。只需知道,一旦我们开始使用像 %User{}
和 %Post{}
这样的结构构建应用程序,我们就可以直接将这些数据结构插入到 ~p
路径中,Phoenix 将提取正确的字段用于该路由。
~p"/users/#{user}/posts/#{post}"
"/users/42/posts/17"
请注意,我们不需要插入 user.id
或 post.id
?如果我们后来决定使 URL 更漂亮,并开始使用 slug 而不是 ID,这将非常方便。我们不需要更改任何 ~p
!
作用域路由
作用域是一种将路由分组到一个公共路径前缀和作用域插头集的方法。我们可能希望这样做来实现管理员功能、API,尤其是针对版本化的 API。假设在一个网站上,我们有用户生成的评论,这些评论需要先由管理员批准。这些资源的语义非常不同,它们可能不会共享相同的控制器。作用域使我们能够隔离这些路由。
面向用户的评论的路径看起来像一个标准资源。
/reviews
/reviews/1234
/reviews/1234/edit
...
管理评论路径可以用 /admin
作为前缀。
/admin/reviews
/admin/reviews/1234
/admin/reviews/1234/edit
...
我们通过一个作用域路由来实现这一点,该路由将路径选项设置为/admin
,就像这样。我们可以将这个作用域嵌套在另一个作用域中,但现在,让我们将其单独设置在根目录,在lib/hello_web/router.ex
中添加以下内容
scope "/admin", HelloWeb.Admin do
pipe_through :browser
resources "/reviews", ReviewController
end
我们定义了一个新的作用域,其中所有路由都以/admin
为前缀,所有控制器都在HelloWeb.Admin
命名空间下。
再次运行mix phx.routes
,除了之前的路由集,我们还得到以下内容
...
GET /admin/reviews HelloWeb.Admin.ReviewController :index
GET /admin/reviews/:id/edit HelloWeb.Admin.ReviewController :edit
GET /admin/reviews/new HelloWeb.Admin.ReviewController :new
GET /admin/reviews/:id HelloWeb.Admin.ReviewController :show
POST /admin/reviews HelloWeb.Admin.ReviewController :create
PATCH /admin/reviews/:id HelloWeb.Admin.ReviewController :update
PUT /admin/reviews/:id HelloWeb.Admin.ReviewController :update
DELETE /admin/reviews/:id HelloWeb.Admin.ReviewController :delete
...
看起来不错,但这里有一个问题。请记住,我们希望用户界面审查路由/reviews
和管理员路由/admin/reviews
。如果现在在我们的路由器中将用户界面审查添加到根作用域中,就像这样
scope "/", HelloWeb do
pipe_through :browser
...
resources "/reviews", ReviewController
end
scope "/admin", HelloWeb.Admin do
pipe_through :browser
resources "/reviews", ReviewController
end
然后我们运行mix phx.routes
,我们得到每个作用域路由的输出
...
GET /reviews HelloWeb.ReviewController :index
GET /reviews/:id/edit HelloWeb.ReviewController :edit
GET /reviews/new HelloWeb.ReviewController :new
GET /reviews/:id HelloWeb.ReviewController :show
POST /reviews HelloWeb.ReviewController :create
PATCH /reviews/:id HelloWeb.ReviewController :update
PUT /reviews/:id HelloWeb.ReviewController :update
DELETE /reviews/:id HelloWeb.ReviewController :delete
...
GET /admin/reviews HelloWeb.Admin.ReviewController :index
GET /admin/reviews/:id/edit HelloWeb.Admin.ReviewController :edit
GET /admin/reviews/new HelloWeb.Admin.ReviewController :new
GET /admin/reviews/:id HelloWeb.Admin.ReviewController :show
POST /admin/reviews HelloWeb.Admin.ReviewController :create
PATCH /admin/reviews/:id HelloWeb.Admin.ReviewController :update
PUT /admin/reviews/:id HelloWeb.Admin.ReviewController :update
DELETE /admin/reviews/:id HelloWeb.Admin.ReviewController :delete
如果我们有很多资源都由管理员处理呢?我们可以将它们全部放在同一个作用域中,就像这样
scope "/admin", HelloWeb.Admin do
pipe_through :browser
resources "/images", ImageController
resources "/reviews", ReviewController
resources "/users", UserController
end
以下是mix phx.routes
告诉我们的内容
...
GET /admin/images HelloWeb.Admin.ImageController :index
GET /admin/images/:id/edit HelloWeb.Admin.ImageController :edit
GET /admin/images/new HelloWeb.Admin.ImageController :new
GET /admin/images/:id HelloWeb.Admin.ImageController :show
POST /admin/images HelloWeb.Admin.ImageController :create
PATCH /admin/images/:id HelloWeb.Admin.ImageController :update
PUT /admin/images/:id HelloWeb.Admin.ImageController :update
DELETE /admin/images/:id HelloWeb.Admin.ImageController :delete
GET /admin/reviews HelloWeb.Admin.ReviewController :index
GET /admin/reviews/:id/edit HelloWeb.Admin.ReviewController :edit
GET /admin/reviews/new HelloWeb.Admin.ReviewController :new
GET /admin/reviews/:id HelloWeb.Admin.ReviewController :show
POST /admin/reviews HelloWeb.Admin.ReviewController :create
PATCH /admin/reviews/:id HelloWeb.Admin.ReviewController :update
PUT /admin/reviews/:id HelloWeb.Admin.ReviewController :update
DELETE /admin/reviews/:id HelloWeb.Admin.ReviewController :delete
GET /admin/users HelloWeb.Admin.UserController :index
GET /admin/users/:id/edit HelloWeb.Admin.UserController :edit
GET /admin/users/new HelloWeb.Admin.UserController :new
GET /admin/users/:id HelloWeb.Admin.UserController :show
POST /admin/users HelloWeb.Admin.UserController :create
PATCH /admin/users/:id HelloWeb.Admin.UserController :update
PUT /admin/users/:id HelloWeb.Admin.UserController :update
DELETE /admin/users/:id HelloWeb.Admin.UserController :delete
太棒了,正是我们想要的。注意每个路由和控制器是如何正确地进行命名空间的。
作用域也可以任意嵌套,但你应该谨慎操作,因为嵌套有时会使代码变得混乱且难以理解。也就是说,假设我们有一个版本化的 API,其中定义了图像、评论和用户的资源。那么从技术上讲,我们可以像这样设置版本化 API 的路由
scope "/api", HelloWeb.Api, as: :api do
pipe_through :api
scope "/v1", V1, as: :v1 do
resources "/images", ImageController
resources "/reviews", ReviewController
resources "/users", UserController
end
end
你可以运行mix phx.routes
来查看这些定义的样子。
有趣的是,我们可以使用具有相同路径的多个作用域,只要我们注意不要重复路由即可。以下路由器完全可以定义两个相同路径的作用域
defmodule HelloWeb.Router do
use Phoenix.Router
...
scope "/", HelloWeb do
pipe_through :browser
resources "/users", UserController
end
scope "/", AnotherAppWeb do
pipe_through :browser
resources "/posts", PostController
end
...
end
如果我们确实重复了一个路由(这意味着两个路由具有相同的路径),我们会收到这个熟悉的警告
warning: this clause cannot match because a previous clause at line 16 always matches
管道
在这份指南中,我们已经走了很远,但没有讨论我们在路由器中看到的第一个代码行之一:pipe_through :browser
。现在是时候解决这个问题了。
管道是一系列可以附加到特定作用域的插件。如果你不熟悉插件,我们有一个关于插件的深入指南。
路由定义在作用域内,作用域可以通过多个管道。一旦路由匹配,Phoenix 会调用与该路由关联的所有管道中定义的所有插件。例如,访问/
将通过:browser
管道,因此将调用其所有插件。
Phoenix 默认定义了两个管道,:browser
和 :api
,它们可用于许多常见任务。反过来,我们可以自定义它们,以及创建新的管道来满足我们的需求。
:browser
和 :api
管道
顾名思义,:browser
管道为渲染浏览器请求的路由做准备,而:api
管道为生成 API 数据的路由做准备。
:browser
管道有六个插件:plug :accepts, ["html"]
定义了接受的请求格式或格式。:fetch_session
,它自然地获取会话数据并将其提供给连接。:fetch_live_flash
,它从 LiveView 获取任何闪存消息并将它们与控制器闪存消息合并。然后,插件:put_root_layout
将存储根布局以用于渲染目的。后面的:protect_from_forgery
和 :put_secure_browser_headers
,保护表单提交免受跨站点伪造攻击。
目前,:api
管道只定义了plug :accepts, ["json"]
。
路由器在一个作用域内定义的路由上调用管道。作用域之外的路由没有管道。尽管不建议使用嵌套作用域(参见上面的版本化 API 示例),但如果我们在嵌套作用域内调用pipe_through
,路由器将调用来自父作用域的所有pipe_through
,然后是嵌套作用域。
这些词语都堆积在一起。让我们看一些例子来理清它们的意思。
这是从一个新生成的 Phoenix 应用程序中获取的路由器的另一个示例,这次/api
作用域已取消注释,并添加了一个路由。
defmodule HelloWeb.Router do
use HelloWeb, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {HelloWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
end
pipeline :api do
plug :accepts, ["json"]
end
scope "/", HelloWeb do
pipe_through :browser
get "/", PageController, :home
end
# Other scopes may use custom stacks.
scope "/api", HelloWeb do
pipe_through :api
resources "/reviews", ReviewController
end
# ...
end
当服务器接受请求时,请求将始终首先通过我们端点中的插件,之后将尝试匹配路径和 HTTP 动词。
假设请求匹配我们的第一个路由:一个 GET 请求到/
。路由器将首先通过:browser
管道传递该请求(它将获取会话数据、获取闪存并执行伪造保护),然后将请求调度到PageController
的home
操作。
相反,假设请求匹配由resources/2
宏定义的任何路由。在这种情况下,路由器将通过:api
管道传递它(目前仅执行内容协商),然后将其进一步调度到HelloWeb.ReviewController
的正确操作。
如果没有任何路由匹配,则不会调用任何管道,并会引发 404 错误。
创建新的管道
Phoenix 允许我们使用以下参数在路由器的任何位置创建我们自己的自定义管道:一个用于新管道名称的原子和一个包含我们想要的所有插件的块。使用pipeline/2
宏调用它
defmodule HelloWeb.Router do
use HelloWeb, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {HelloWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
end
pipeline :auth do
plug HelloWeb.Authentication
end
scope "/reviews", HelloWeb do
pipe_through [:browser, :auth]
resources "/", ReviewController
end
end
上面假设存在一个名为HelloWeb.Authentication
的插件,它执行身份验证,现在是:auth
管道的部分。
请注意,管道本身是插件,因此我们可以将管道插入另一个管道中。例如,我们可以重写上面的auth
管道来自动调用browser
,简化下游管道调用
pipeline :auth do
plug :browser
plug :ensure_authenticated_user
plug :ensure_user_owns_review
end
scope "/reviews", HelloWeb do
pipe_through :auth
resources "/", ReviewController
end
如何组织我的路由?
在 Phoenix 中,我们倾向于定义几个管道,它们提供特定的功能。例如,:browser
和 :api
管道旨在分别被特定客户端、浏览器和 http 客户端访问。
也许更重要的是,定义特定于身份验证和授权的管道也很常见。例如,你可能有一个管道要求所有用户都经过身份验证。另一个管道可能强制执行只有管理员用户才能访问某些路由。
定义好管道后,你就可以在所需的作用域中重用管道,将路由分组到它们的管道周围。例如,回到我们的评论示例。假设任何人都可以阅读评论,但只有经过身份验证的用户才能创建评论。你的路由可能如下所示
pipeline :browser do
...
end
pipeline :auth do
plug HelloWeb.Authentication
end
scope "/" do
pipe_through [:browser]
get "/reviews", PostController, :index
get "/reviews/:id", PostController, :show
end
scope "/" do
pipe_through [:browser, :auth]
get "/reviews/new", PostController, :new
post "/reviews", PostController, :create
end
请注意,在上面的代码中,路由是如何跨不同作用域拆分的。虽然这种分离一开始可能令人困惑,但它有一个很大的好处:检查路由并查看例如需要身份验证的所有路由以及哪些路由不需要身份验证非常容易。这有助于审核并确保你的路由具有正确的范围。
你可以创建尽可能少或尽可能多的作用域。由于管道可以在作用域之间重用,因此它们有助于封装通用功能,你可以根据需要将它们组合在定义的每个作用域上。
转发
Phoenix.Router.forward/4
宏可用于将所有以特定路径开头的请求发送到特定插件。假设我们有一个系统的一部分(甚至可以是单独的应用程序或库)负责在后台运行作业,它可能有自己的 Web 界面用于检查作业的状态。我们可以使用以下方法转发到这个管理界面
defmodule HelloWeb.Router do
use HelloWeb, :router
...
scope "/", HelloWeb do
...
end
forward "/jobs", BackgroundJob.Plug
end
这意味着所有以/jobs
开头的路由都将发送到HelloWeb.BackgroundJob.Plug
模块。在插件内部,你可以匹配子路由,例如/pending
和 /active
,它们显示了某些作业的状态。
我们甚至可以将forward/4
宏与管道混合使用。如果我们想确保用户已通过身份验证并且是管理员才能查看作业页面,我们可以在路由器中使用以下方法。
defmodule HelloWeb.Router do
use HelloWeb, :router
...
scope "/" do
pipe_through [:authenticate_user, :ensure_admin]
forward "/jobs", BackgroundJob.Plug
end
end
这意味着authenticate_user
和 ensure_admin
管道中的插件将在BackgroundJob.Plug
之前调用,允许它们相应地发送适当的响应并停止请求。
可以在模块插件的init/1
回调中接收到的opts
作为第三个参数传递。例如,也许后台作业允许你设置要显示在页面上的应用程序名称。这可以通过以下方式传递
forward "/jobs", BackgroundJob.Plug, name: "Hello Phoenix"
还有一个第四个可以传递的router_opts
参数。这些选项在Phoenix.Router.scope/2
文档中概述。
BackgroundJob.Plug
可以实现为插件指南中讨论的任何模块插件。但请注意,不建议转发到另一个 Phoenix 端点。这是因为你的应用程序和转发端点定义的插件将被调用两次,这可能会导致错误。
摘要
路由是一个很大的主题,我们在这里已经涵盖了很多内容。从本指南中要带走的重要要点是
- 以 HTTP 动词名称开头的路由扩展到匹配函数的一个子句。
- 用
resources
声明的路由扩展到匹配函数的 8 个子句。 - 资源可以使用
only:
或except:
选项来限制匹配函数子句的数量。 - 所有这些路由都可以嵌套。
- 所有这些路由都可以限定到给定的路径。
- 使用经过验证的路由,使用
~p
进行编译时路由检查