Phoenix.Router
Исходный кодОпределяет маршрутизатор Phoenix.
Маршрутизатор предоставляет набор макросов для создания маршрутов, перенаправляющих запросы к определённым контроллерам и действиям. Эти макросы названы в соответствии с HTTP-методами. Например:
defmodule MyAppWeb.Router do use Phoenix.Router get "/pages/:page", PageController, :show end
Макрос get/3, приведённый выше, принимает запрос к /pages/hello и перенаправляет его к действию show контроллера PageController с %{"page" => "hello"} в params.
Маршрутизатор Phoenix чрезвычайно эффективен, поскольку использует сопоставление с образцом в Elixir для сопоставления маршрутов и обработки запросов.
Маршрутизация
Для создания маршрутов используются макросы get/3, post/3, put/3 и другие макросы, названные в соответствии с HTTP-методами.
Маршрут:
get "/pages", PageController, :index
сопоставляется с запросом GET к /pages и перенаправляет его к действию index в PageController.
get "/pages/:page", PageController, :show
сопоставляется с /pages/hello и перенаправляет запрос к действию show с %{"page" => "hello"} в params.
defmodule PageController do
def show(conn, params) do
# %{"page" => "hello"} == params
end
end
Можно сопоставлять частичные и множественные сегменты. Например:
get "/api/v:version/pages/:id", PageController, :show
сопоставляется с /api/v1/pages/2 и помещает %{"version" => "1", "id" => "2"} в params. Захватить можно только конечную часть сегмента.
Маршруты сопоставляются сверху вниз. Второй маршрут здесь:
get "/pages/:page", PageController, :show get "/pages/hello", PageController, :hello
никогда не сопоставится с /pages/hello, поскольку первым с ним сопоставляется /pages/:page.
В маршрутах можно использовать шаблоны, похожие на glob, для сопоставления конечных сегментов.
get "/pages/*page", PageController, :show
сопоставляется с /pages/hello/world и помещает сегменты, сопоставленные с помощью glob-шаблона, в params["page"].
GET /pages/hello/world
%{"page" => ["hello", "world"]} = params
У glob-шаблонов не может быть префиксов и суффиксов, но их можно сочетать с переменными:
get "/pages/he:page/*rest", PageController, :show
сопоставляется с
GET /pages/hello
%{"page" => "llo", "rest" => []} = params
GET /pages/hey/there/world
%{"page" => "y", "rest" => ["there" "world"]} = params
Зачем нужны макросы?
Phoenix старается свести использование макросов к минимуму. Однако вы могли заметить, что Phoenix.Router активно использует макросы. Почему?
Для определения маршрутов используются get, post, put и delete. Макросы применяются для двух целей:
Они определяют механизм маршрутизации, который используется при каждом запросе для выбора контроллера, которому нужно его передать. Благодаря макросам Phoenix компилирует все ваши маршруты в один оператор case с правилами сопоставления с образцом, который VM Erlang значительно оптимизирует
Для каждого определённого вами маршрута мы также создаём метаданные, необходимые для реализации
Phoenix.VerifiedRoutes. Как мы скоро узнаем, проверенные маршруты позволяют ссылаться на любой маршрут как на обычную строку, при этом компилятор проверяет её корректность (что значительно снижает вероятность отправки в рабочую среду неработающих ссылок, форм, писем и т. д.)
Иными словами, маршрутизатор использует макросы для создания более быстрых и безопасных приложений. Также помните, что макросы в Elixir работают только на этапе компиляции, что обеспечивает высокую стабильность после компиляции кода. Phoenix также позволяет получать информацию обо всех определённых маршрутах с помощью задачи mix phx.routes.
Создание маршрутов
Чтобы создавать маршруты в приложении, ознакомьтесь с документацией Phoenix.VerifiedRoutes по созданию маршрутов на основе ~p — предпочтительному способу создания путей и URL-адресов маршрутов с проверкой во время компиляции.
Phoenix также поддерживает создание функциональных помощников — механизм, использовавшийся по умолчанию в Phoenix v1.6 и более ранних версиях. Рассмотрим его далее.
Помощники (устарели)
По умолчанию Phoenix создаёт внутри маршрутизатора модуль Helpers, содержащий именованные помощники, которые помогают разработчикам создавать маршруты и поддерживать их актуальность. Чтобы отключить помощники, передайте helpers: false в use Phoenix.Router.
Помощники создаются автоматически на основе имени контроллера. Например, маршрут:
get "/pages/:page", PageController, :show
создаст следующий именованный помощник:
MyAppWeb.Router.Helpers.page_path(conn_or_endpoint, :show, "hello") "/pages/hello" MyAppWeb.Router.Helpers.page_path(conn_or_endpoint, :show, "hello", some: "query") "/pages/hello?some=query" MyAppWeb.Router.Helpers.page_url(conn_or_endpoint, :show, "hello") "http://example.com/pages/hello" MyAppWeb.Router.Helpers.page_url(conn_or_endpoint, :show, "hello", some: "query") "http://example.com/pages/hello?some=query"
Если маршрут содержит шаблоны, похожие на glob, соответствующие параметры необходимо передать в виде списка:
MyAppWeb.Router.Helpers.page_path(conn_or_endpoint, :show, ["hello", "world"]) "/pages/hello/world"
URL-адрес, создаваемый именованными помощниками URL, зависит от конфигурации :url, :http и :https. Однако, если по какой-либо причине вам нужно управлять созданием URL вручную, помощникам URL также можно передать структуру URI:
uri = %URI{scheme: "https", host: "other.example.com"}
MyAppWeb.Router.Helpers.page_url(uri, :show, "hello")
"https://other.example.com/pages/hello"
Именованный помощник также можно настроить с помощью параметра :as. Для маршрута:
get "/pages/:page", PageController, :show, as: :special_page
именованный помощник будет таким:
MyAppWeb.Router.Helpers.special_page_path(conn, :show, "hello") "/pages/hello"
Области и ресурсы
В приложениях Phoenix часто все маршруты помещают в пространство имён области приложения:
scope "/", MyAppWeb do get "/pages/:id", PageController, :show end
Приведённый выше маршрут перенаправит запрос к MyAppWeb.PageController. Такой синтаксис удобен для разработчиков, поскольку позволяет не повторять префикс MyAppWeb. во всех маршрутах.
Как и для всех путей, можно определить динамические сегменты, которые будут переданы в контроллер в качестве параметров:
scope "/api/:version", MyAppWeb do get "/pages/:id", PageController, :show end
Например, приведённый выше маршрут сопоставится с путём "/api/v1/pages/1", а аргумент params в контроллере будет содержать карту с ключом :version и значением "v1".
Phoenix также предоставляет макрос resources/4, позволяющий разработчикам создавать «RESTful»-маршруты для заданного ресурса:
defmodule MyAppWeb.Router do use Phoenix.Router, helpers: false resources "/pages", PageController, only: [:show] resources "/users", UserController, except: [:delete] end
Наконец, Phoenix включает задачу mix phx.routes, которая наглядно форматирует все маршруты заданного маршрутизатора. С её помощью можно проверить все маршруты, включённые в приведённый выше маршрутизатор:
$ mix phx.routes GET /pages/:id PageController.show/2 GET /users UserController.index/2 GET /users/:id/edit UserController.edit/2 GET /users/new UserController.new/2 GET /users/:id UserController.show/2 POST /users UserController.create/2 PATCH /users/:id UserController.update/2 PUT /users/:id UserController.update/2
Маршрутизатор также можно явно передать задаче в качестве аргумента:
$ mix phx.routes MyAppWeb.Router
Дополнительную информацию см. в разделах scope/2 и resources/4.
Конвейеры и плагины
Когда запрос поступает в маршрутизатор Phoenix, он проходит через ряд преобразований в конвейерах, пока не будет перенаправлен к нужному маршруту.
Эти преобразования задаются с помощью плагинов, как определено в спецификации Plug. После определения конвейера его можно подключить к каждой области.
Например:
defmodule MyAppWeb.Router do
use Phoenix.Router
pipeline :browser do
plug :fetch_session
plug :accepts, ["html"]
end
scope "/" do
pipe_through :browser
# browser related routes and resources
end
end
Phoenix.Router импортирует функции из Plug.Conn и Phoenix.Controller, помогающие определять плагины. В приведённом выше примере fetch_session/2 импортирован из Plug.Conn, а accepts/2 — из Phoenix.Controller.
Обратите внимание: конвейеры маршрутизатора запускаются только после обнаружения маршрута. Если совпадений не найдено, плагины не запускаются.
Дополнительная информация
Дополнительную информацию и примеры использования в приложении Phoenix см. в руководстве «Маршрутизация».
Краткое описание
- route_info(router, method, path, host)
Возвращает информацию о маршруте на этапе компиляции и параметры пути во время выполнения для запроса.
- scoped_alias(router_module, alias)
Возвращает полный псевдоним с префиксом псевдонима текущей области.
- scoped_path(router_module, path)
Возвращает полный путь с префиксом пути текущей области.
Рефлексия
- connect(path, plug, plug_opts, options \\ [])
Создаёт маршрут для обработки CONNECT-запроса к заданному пути.
- delete(path, plug, plug_opts, options \\ [])
Создаёт маршрут для обработки DELETE-запроса к заданному пути.
- forward(path, plug, plug_opts \\ [], router_opts \\ [])
Перенаправляет запрос по заданному пути к плагину.
- get(path, plug, plug_opts, options \\ [])
Создаёт маршрут для обработки GET-запроса к заданному пути.
- head(path, plug, plug_opts, options \\ [])
Создаёт маршрут для обработки HEAD-запроса к заданному пути.
- match(verb, path, plug, plug_opts, options \\ [])
Создаёт сопоставление маршрута на основе произвольного HTTP-метода.
- options(path, plug, plug_opts, options \\ [])
Создаёт маршрут для обработки OPTIONS-запроса к заданному пути.
- patch(path, plug, plug_opts, options \\ [])
Создаёт маршрут для обработки PATCH-запроса к заданному пути.
- pipe_through(pipes)
Определяет список плагинов (и конвейеров), через которые проходит соединение.
- pipeline(plug, list)
Определяет конвейер плагинов.
- plug(plug, opts \\ [])
Определяет плагин внутри конвейера.
- post(path, plug, plug_opts, options \\ [])
Создаёт маршрут для обработки POST-запроса к заданному пути.
- put(path, plug, plug_opts, options \\ [])
Создаёт маршрут для обработки PUT-запроса к заданному пути.
- resources(path, controller, opts, list)
Определяет «RESTful»-маршруты для ресурса.
- routes(router)
Возвращает сведения обо всех маршрутах заданного маршрутизатора.
- scope(options, list)
Определяет область, внутри которой можно вкладывать маршруты.
- scope(path, options, list)
Определяет область с заданным путём.
- scope(path, alias, options, list)
Определяет область с заданными путём и псевдонимом.
- trace(path, plug, plug_opts, options \\ [])
Создаёт маршрут для обработки TRACE-запроса к заданному пути.
Функции
Рефлексия
route_info(router, method, path, host)Исходный код
Возвращает информацию о маршруте на этапе компиляции и параметры пути во время выполнения для запроса.
Значение path может быть строкой или сегментами path_info.
Возвращается карта метаданных со следующими ключами:
-
:log— настроенный уровень журналирования. Например,:debug -
:path_params— карта параметров пути во время выполнения -
:pipe_through— список конвейеров для области маршрута, например[:browser] -
:plug— плагин, которому передаётся маршрут, напримерAppWeb.PostController -
:plug_opts— параметры, передаваемые при вызове плагина, например::index -
:route— строковый шаблон маршрута, например"/posts/:id"
Примеры
iex> Phoenix.Router.route_info(AppWeb.Router, "GET", "/posts/123", "myhost")
%{
log: :debug,
path_params: %{"id" => "123"},
pipe_through: [:browser],
plug: AppWeb.PostController,
plug_opts: :show,
route: "/posts/:id",
}
iex> Phoenix.Router.route_info(MyRouter, "GET", "/not-exists", "myhost")
:error scoped_alias(router_module, alias)Исходный код
Возвращает полный псевдоним с префиксом псевдонима текущей области.
Полезно для применения той же сокращённой обработки псевдонимов к значениям, отличным от второго аргумента в определениях маршрутов.
Примеры
scope "/", MyPrefix do get "/", ProxyPlug, controller: scoped_alias(__MODULE__, MyController) end
scoped_path(router_module, path)Исходный код
Возвращает полный путь с префиксом пути текущей области.
Функции
connect(path, plug, plug_opts, options \\ [])Источник
Создаёт маршрут для обработки connect-запроса по указанному пути.
connect("/events/:id", EventController, :action)
Сведения о параметрах см. в разделе match/5.
delete(path, plug, plug_opts, options \\ [])Источник
Создаёт маршрут для обработки delete-запроса по указанному пути.
delete("/events/:id", EventController, :action)
Сведения о параметрах см. в разделе match/5.
forward(path, plug, plug_opts \\ [], router_opts \\ [])Источник
Перенаправляет запрос по указанному пути в plug.
Чаще всего это используется для перенаправления всех вложенных маршрутов в другой Plug. Например:
forward "/admin", SomeLib.AdminDashboard
Это позволит SomeLib.AdminDashboard обрабатывать /admin, /admin/foo, /admin/bar/baz и так далее. Кроме того, SomeLib.AdminDashboard не нужно знать префикс, с которым он подключён. С его точки зрения, указанные выше маршруты обрабатываются как /, /foo и /bar/baz.
Обычный сценарий использования forward — совместное использование маршрутизатора несколькими приложениями или разделение большого маршрутизатора на несколько меньших. Однако для корректной генерации маршрутов можно перенаправить запросы только в один экземпляр Phoenix.Router.
Перед перенаправлением соединения будут выполнены конвейеры маршрутизатора.
Примеры
scope "/", MyApp do pipe_through [:browser, :admin] forward "/admin", SomeLib.AdminDashboard forward "/api", ApiRouter end
get(path, plug, plug_opts, options \\ [])Источник
Создаёт маршрут для обработки get-запроса по указанному пути.
get("/events/:id", EventController, :action)
Сведения о параметрах см. в разделе match/5.
head(path, plug, plug_opts, options \\ [])Источник
Создаёт маршрут для обработки head-запроса по указанному пути.
head("/events/:id", EventController, :action)
Сведения о параметрах см. в разделе match/5.
Совместимость с Plug.Head
По умолчанию приложения Phoenix включают Plug.Head в свою конечную точку, где HEAD-запросы преобразуются в обычные GET-запросы. Поэтому, если вы хотите использовать head/4 в маршрутизаторе, необходимо переместить Plug.Head внутрь маршрутизатора так, чтобы он не конфликтовал с путями, указанными в head/4.
match(verb, path, plug, plug_opts, options \\ [])Источник
Создаёт маршрут, соответствующий произвольному методу HTTP.
Полезно для определения маршрутов, не включённых во встроенные макросы.
Также можно использовать универсальный метод :* для сопоставления со всеми методами HTTP.
Параметры
-
:as— задаёт именованный helper. Если указаноnil, helper не создаётся. Не действует, если используются только проверяемые маршруты -
:alias— определяет, следует ли применять к маршруту псевдоним области видимости. По умолчанию — true; если задано false, область видимости не применяется. -
:log— уровень журналирования диспетчеризации маршрута; можно задать false. По умолчанию —:debug. Запись диспетчеризации содержит сведения об обработке маршрута (какое действие контроллера вызывается, какие параметры доступны и какие конвейеры используются) и ведётся отдельно от журналирования на уровне plug. Чтобы изменить уровень журналирования plug, см. https://phoenix.hexdocs.pm/Phoenix.Logger.html#module-dynamic-log-level. -
:private— карта приватных данных, добавляемых к соединению при совпадении маршрута -
:assigns— карта данных, добавляемых к соединению при совпадении маршрута -
:metadata— карта метаданных, используемых событиями telemetry и возвращаемых функциейroute_info/4. Поле:mfaиспользуется telemetry для вывода журналов, а маршрутизатором — для выполнения проверок во время компиляции. Можно добавлять пользовательские поля. -
:warn_on_verify— логическое значение, определяющее, будет ли совпадение с этим маршрутом вызывать предупреждение о несопоставленном маршруте дляPhoenix.VerifiedRoutes. Это позволяет исключить из проверки маршрутов совпадение с определением маршрута, которое в противном случае охватывало бы все случаи. По умолчанию —false.
Примеры
match(:move, "/events/:id", EventController, :move) match(:*, "/any", SomeController, :any)
options(path, plug, plug_opts, options \\ [])Источник
Создаёт маршрут для обработки options-запроса по указанному пути.
options("/events/:id", EventController, :action)
Сведения о параметрах см. в разделе match/5.
patch(path, plug, plug_opts, options \\ [])Источник
Создаёт маршрут для обработки patch-запроса по указанному пути.
patch("/events/:id", EventController, :action)
Сведения о параметрах см. в разделе match/5.
pipe_through(pipes)Источник
Определяет список plug (и конвейеров), через которые проходит соединение.
Plug указываются атомарным именем любой импортированной функции с арностью 2, которая принимает Plug.Conn и параметры и возвращает Plug.Conn. Например, :require_authenticated_user.
Конвейеры определяются в маршрутизаторе; дополнительную информацию см. в разделе pipeline/2.
pipe_through [:require_authenticated_user, :my_browser_pipeline]
Несколько вызовов
Функцию pipe_through/1 можно вызывать несколько раз в одной области видимости. Каждый вызов добавляет новые plug и конвейеры, которые будут применяться ко всем маршрутам, определённым после вызова pipe_through/1. Например:
scope "/" do pipe_through [:browser] get "/", HomeController, :index pipe_through [:require_authenticated_user] get "/settings", UserController, :edit end
В примере выше / проходит только через browser, а /settings — через browser и require_authenticated_user. Поэтому, чтобы избежать путаницы, рекомендуем использовать один pipe_through в начале каждой области видимости:
scope "/" do pipe_through [:browser] get "/", HomeController, :index end scope "/" do pipe_through [:browser, :require_authenticated_user] get "/settings", UserController, :edit end
pipeline(plug, list)Источник
Определяет конвейер plug.
Конвейеры определяются в корне маршрутизатора и могут использоваться из любой области видимости.
Примеры
pipeline :api do plug :token_authentication plug :dispatch end
Затем область видимости может использовать этот конвейер следующим образом:
scope "/" do pipe_through :api end
При каждом вызове pipe_through/1 новые конвейеры добавляются к указанным ранее.
plug(plug, opts \\ [])Источник
Определяет plug внутри конвейера.
Дополнительную информацию см. в разделе pipeline/2.
post(path, plug, plug_opts, options \\ [])Источник
Создаёт маршрут для обработки post-запроса по указанному пути.
post("/events/:id", EventController, :action)
Сведения о параметрах см. в разделе match/5.
put(path, plug, plug_opts, options \\ [])Источник
Создаёт маршрут для обработки put-запроса по указанному пути.
put("/events/:id", EventController, :action)
Сведения о параметрах см. в разделе match/5.
resources(path, controller)Источник
См. resources/4.
resources(path, controller, opts)Источник
См. resources/4.
resources(path, controller, opts, list)Источник
Определяет маршруты «RESTful» для ресурса.
Указанное определение:
resources "/users", UserController
будет включать маршруты для следующих действий:
-
GET /users=>:index -
GET /users/new=>:new -
POST /users=>:create -
GET /users/:id=>:show -
GET /users/:id/edit=>:edit -
PATCH /users/:id=>:update -
PUT /users/:id=>:update -
DELETE /users/:id=>:delete
Параметры
Этот макрос принимает набор параметров:
-
:only— список действий, для которых нужно создать маршруты, например:[:show, :edit] -
:except— список действий, для которых не нужно создавать маршруты, например:[:delete] -
:param— имя параметра этого ресурса; по умолчанию —"id" -
:name— префикс этого ресурса. Используется для именованного helper и как префикс параметра во вложенных ресурсах. Значение по умолчанию автоматически определяется по имени контроллера: например,UserControllerбудет иметь имя"user" -
:as— задаёт именованный helper. Если указаноnil, helper не создаётся. Не действует, если используются только проверяемые маршруты -
:singleton— определяет маршруты для одиночного ресурса, который клиент запрашивает без указания идентификатора. Подробнее см. ниже
Одиночные ресурсы
Если ресурс нужно запрашивать без указания идентификатора, поскольку в заданном контексте он содержит только одну запись, можно использовать параметр :singleton, чтобы создать набор маршрутов для такого одиночного ресурса:
-
GET /user=>:show -
GET /user/new=>:new -
POST /user=>:create -
GET /user/edit=>:edit -
PATCH /user=>:update -
PUT /user=>:update -
DELETE /user=>:delete
Пример использования:
resources "/account", AccountController, only: [:show], singleton: true
Вложенные ресурсы
Этот макрос также поддерживает передачу вложенного блока определений маршрутов. Это удобно для вложения дочерних ресурсов в родительские и создания вложенных маршрутов.
Указанное определение:
resources "/users", UserController do resources "/posts", PostController end
будет включать следующие маршруты:
user_post_path GET /users/:user_id/posts PostController :index
user_post_path GET /users/:user_id/posts/:id/edit PostController :edit
user_post_path GET /users/:user_id/posts/new PostController :new
user_post_path GET /users/:user_id/posts/:id PostController :show
user_post_path POST /users/:user_id/posts PostController :create
user_post_path PATCH /users/:user_id/posts/:id PostController :update
PUT /users/:user_id/posts/:id PostController :update
user_post_path DELETE /users/:user_id/posts/:id PostController :delete
routes(router)Источник
Возвращает сведения обо всех маршрутах указанного маршрутизатора.
scope(options, list)Источник
Определяет область видимости, внутри которой можно размещать вложенные маршруты.
Примеры
scope path: "/api/v1", alias: API.V1 do get "/pages/:id", PageController, :show end
Созданный маршрут будет соответствовать пути "/api/v1/pages/:id" и направлять запрос к действию :show в API.V1.PageController. Также будет создан именованный helper api_v1_page_path.
Параметры
Поддерживаются следующие параметры:
-
:path— строка, содержащая область видимости пути. -
:as— строка или атом, содержащие область видимости именованного helper. Если задано false, сбрасывает вложенные области видимости helper. Не действует, если используются только проверяемые маршруты -
:alias— псевдоним (атом), содержащий область видимости контроллера. Если задано false, сбрасывает все вложенные псевдонимы. -
:host— строка или список строк, содержащих область видимости хоста либо префикс области видимости хоста, например"foo.bar.com","foo." -
:private— карта приватных данных, добавляемых к соединению при совпадении маршрута -
:assigns— карта данных, добавляемых к соединению при совпадении маршрута -
:log— уровень журналирования диспетчеризации маршрута; можно задать false. По умолчанию —:debug. Запись диспетчеризации содержит сведения об обработке маршрута (какое действие контроллера вызывается, какие параметры доступны и какие конвейеры используются) и ведётся отдельно от журналирования на уровне plug. Чтобы изменить уровень журналирования plug, см. https://phoenix.hexdocs.pm/Phoenix.Logger.html#module-dynamic-log-level.
scope(path, options, list)Источник
Определяет область видимости с указанным путём.
Эта функция является сокращённой записью для:
scope path: path do ... end
Примеры
scope "/v1", host: "api." do get "/pages/:id", PageController, :show end
scope(path, alias, options, list)Источник
Определяет область видимости с указанными путём и псевдонимом.
Эта функция является сокращённой записью для:
scope path: path, alias: alias do ... end
Примеры
scope "/v1", API.V1, host: "api." do get "/pages/:id", PageController, :show end
trace(path, plug, plug_opts, options \\ [])Источник
Создаёт маршрут для обработки trace-запроса по указанному пути.
trace("/events/:id", EventController, :action)
Сведения о параметрах см. в разделе match/5.
© 2014 Chris McCord
Licensed under the MIT License.
https://phoenix.hexdocs.pm/Phoenix.Router.html