Spec-Zone.ru › Phoenix

Phoenix.VerifiedRoutes поведение

Исходный код

Предоставляет генерацию маршрутов с проверкой во время компиляции.

Использование макроса sigil_p позволяет проверять пути и URL-адреса во всём приложении во время компиляции на соответствие маршрутизаторам Phoenix. Например, следующие варианты использования путей и URL-адресов:

~H"""
<a href={~p"/sessions/new"}>Log in</a>
"""

redirect(to: url(~p"/posts/#{post}"))

Будут проверены на соответствие стандартным определениям Phoenix.Router:

get "/posts/:post_id", PostController, :show
post "/sessions/new", SessionController, :create

Для несовпадающих маршрутов компилятор выдаст предупреждения:

warning: no route path for AppWeb.Router matches "/postz/#{post}"
  lib/app_web/controllers/post_controller.ex:100: AppWeb.PostController.show/2

Кроме того, интерполируемые значения ~p кодируются с помощью протокола Phoenix.Param. Например, структура %Post{} в вашем приложении может реализовывать протокол Phoenix.Param, чтобы создавать пути на основе слагов, а не идентификаторов. Это позволяет использовать ~p"/posts/#{post}" вместо ~p"/posts/#{post.slug}" во всём приложении. Дополнительные сведения см. в документации Phoenix.Param.

Наконец, в проверяемых маршрутах поддерживаются и строки запроса — как в традиционной форме:

~p"/posts?page=#{page}"

Так и в виде ключевого списка или карты значений:

params = %{page: 1, direction: "asc"}
~p"/posts?#{params}"

Как и сегменты пути, параметры строки запроса корректно кодируются для URL и могут интерполироваться непосредственно в строку ~p.

Чтобы упростить сравнение URL во время тестов (например, при использовании assert_redirect/3), параметры запроса будут отсортированы. Это регулируется параметром конфигурации phoenix: [sort_verified_routes_query_params: true].

Что насчёт именованных маршрутов?

Многие веб-фреймворки и ранние версии Phoenix предоставляли функцию под названием «именованные маршруты». Идея заключается в том, что при определении маршрутов в веб-приложении им можно также присвоить имена. В Phoenix это делалось следующим образом:

get "/login", SessionController, :create, as: :login

Теперь можно было сгенерировать маршрут с помощью функции login_path.

Именованные маршруты позволяют избежать жёсткого задания маршрутов в шаблонах: если написать <a href="/login">, а затем изменить маршрутизатор, ссылка будет указывать на несуществующую страницу. Используя login_path, мы гарантируем, что ссылка всегда будет указывать на действительный URL в нашем маршрутизаторе. Однако у именованных маршрутов есть недостаток — необходимость косвенного обращения: при чтении кода не сразу понятно, какой URL будет сгенерирован. Кроме того, если у вас есть URL и вы хотите добавить его в шаблон, нужно выполнить обратный поиск и найти его имя в маршрутизаторе. В конечном счёте именованные маршруты — это произвольные имена, которые разработчикам приходится запоминать, что увеличивает когнитивную нагрузку.

Проверяемые маршруты решают эту проблему, позволяя записывать маршруты так, как мы видим их в браузере, и при этом использовать сигил ~p, чтобы гарантировать их существование на этапе компиляции. Они устраняют необходимость косвенного обращения к именованным маршрутам, сохраняя при этом гарантии.

В любом случае, если для части приложения нужны функции, похожие на именованные маршруты, помните, что для достижения того же результата можно использовать возможности Elixir. Например, можно определить несколько функций как именованные маршруты и повторно использовать их в разных модулях:

def login_path, do: ~p"/login"
def user_home_path(user), do: ~p"/users/#{user.username}"

Параметры

Чтобы проверять маршруты в модулях приложения, таких как контроллеры, шаблоны и представления, используйте use Phoenix.VerifiedRoutes, который поддерживает следующие параметры:

  • :router — обязательный маршрутизатор, относительно которого проверяются пути ~p
  • :endpoint — необязательная конечная точка для генерации URL
  • :statics — необязательный список статических каталогов, которые следует считать проверяемыми путями
  • :path_prefixes — необязательный список префиксов путей, добавляемых ко всем сгенерированным путям. Дополнительные сведения см. в разделе «Префиксы путей»

Например:

use Phoenix.VerifiedRoutes,
  router: AppWeb.Router,
  endpoint: AppWeb.Endpoint,
  statics: ~w(images)

Генерация маршрутов на основе соединения/сокета

Большинство потребностей приложения в генерации путей и URL можно удовлетворить с помощью ~p и url/1: вся необходимая для построения пути или URL информация предоставляется во время компиляции из данных Endpoint и Router, переданных в use Phoenix.VerifiedRoutes.

Тем не менее в некоторых случаях требуются path/2, path/3, url/2 и url/3:

  • Когда значения %Plug.Conn{}, %Phoenix.LiveSocket{} или %URI{} во время выполнения определяют формирование пути или URL, что происходит в следующих случаях:

    • Phoenix.Controller.put_router_url/2 используется для переопределения URL конечной точки
    • Phoenix.Controller.put_static_url/2 используется для переопределения статического URL конечной точки
  • Когда модуль Router отличается от переданного в use Phoenix.VerifiedRoutes, например в коде библиотеки или приложения, использующего несколько маршрутизаторов. В таких случаях модуль маршрутизатора можно явно передать в path/3 и url/3.

Отслеживание предупреждений

Все статические сегменты пути должны начинаться с косой черты, а между динамическими интерполяциями должен находиться статический сегмент, чтобы маршрут проверялся без предупреждений. Например, предположим, что у вас есть два следующих маршрута:

get "/media/posts/:id"
get "/media/images/:id"

Следующий маршрут будет проверен и выдаст предупреждение, поскольку он не соответствует маршрутизатору:

~p"/media/post/#{post}"

Однако маршрут ниже проверен не будет: сегмент «post» является динамическим:

type = "post"
~p"/media/#{type}/#{post}"

Если вам требуется генерировать динамические URL, которые статически определены в маршрутизаторе, это хороший повод реорганизовать код и вынести их в одну или несколько функций, например posts_path/1 и images_path/1.

Как и при любом другом предупреждении компиляции, компилятор Elixir выдаёт предупреждение при каждом изменении файла, в котором находится ~p, а также при изменении маршрутизатора.

Локализованные маршруты и префиксы путей

Приложениям, которым необходима поддержка интернационализации (i18n) и локализации (l10n), часто требуется реализовать её на уровне URL. В таких случаях можно выбрать один из нескольких подходов.

Один из вариантов — реализовать i18n на уровне домена. Можно использовать example.com (в этом случае локаль определяется по HTTP-заголовку «Accept-Language»), en.example.com, en-GB.example.com и так далее. В этом случае плагин анализирует хост и HTTP-заголовки и соответствующим образом вызывает Gettext.get_locale/1. Главное преимущество такого подхода — отсутствие необходимости менять маршруты в приложении: проверяемые маршруты продолжат работать без изменений.

Однако в некоторых приложениях локаль добавляют в качестве префикса URL:

scope "/:locale" do
  get "/posts"
  get "/images"
end

Для таких случаев VerifiedRoutes позволяет настроить параметр path_prefixes — список сегментов, добавляемых в начало URL. Например:

use Phoenix.VerifiedRoutes,
  router: AppWeb.Router,
  endpoint: AppWeb.Endpoint,
  path_prefixes: [{Gettext, :get_locale, []}]

В приведённом выше примере "/#{Gettext.get_locale()}" добавляется в начало каждого пути и URL, созданного с помощью ~p. Если на вашем сайте есть несколько URL, которым не нужен префикс локали, рекомендуем определить их в отдельном модуле и использовать Phoenix.VerifiedRoutes без параметра префикса:

defmodule UnlocalizedRoutes do
  use Phoenix.VerifiedRoutes,
    router: AppWeb.Router,
    endpoint: AppWeb.Endpoint

  # Since :path_prefixes was not declared,
  # the code below won't prepend the locale and still be verified
  def root, do: ~p"/"
end

Наконец, для ещё более сложных случаев, когда требуется локализовать URL целиком, рассмотрите такие проекты, как routex и ex_cldr_routes.

Использование с пользовательскими плагинами

Иногда при динамической маршрутизации мы перенаправляем запросы в пользовательские плагины. Такие динамические маршрутизаторы можно научить поддерживать mix phx.routes и проверяемые маршруты во время компиляции, реализовав поведение Phoenix.VerifiedRoutes. Например:

defmodule MyApp.LocaleRouter do
  use Plug.Router
  @behaviour Phoenix.VerifiedRoutes

  # custom routing rules

  # for displaying in `mix phx.routes`
  def formatted_routes(plug_opts) do
    for locale <- supported_locales(plug_opts) do
      %{verb: "GET", path: "/#{locale}/*subpath"}
    end
  end

  def verified_route?(plug_opts, path) do
    plug_opts
    |> supported_locales()
    |> Enum.any?(fn locale ->
      Enum.at(path, 0) == locale
    end)
  end
end

Краткое описание

Типы

formatted_route()
plug_opts()

Обратные вызовы

formatted_routes(plug_opts)

Возвращает необходимую информацию о маршрутах для отображения в mix phx.routes.

verified_route?(plug_opts, list)

Возвращает true, если путь проверен, и false в противном случае.

Функции

path(conn_or_socket_or_endpoint_or_uri, sigil_p)

Генерирует путь маршрутизатора с проверкой маршрута.

path(conn_or_socket_or_endpoint_or_uri, router, sigil_p)

Генерирует путь маршрутизатора с проверкой маршрута.

sigil_p(route, extra)

Генерирует путь маршрутизатора с проверкой маршрута.

static_integrity(conn_or_socket_or_endpoint, path)

Генерирует хеш целостности статического ресурса по пути к его файлу.

static_path(conn_or_socket_or_endpoint_or_uri, path)

Генерирует путь к статическому ресурсу по пути к его файлу.

static_url(conn_or_socket_or_endpoint, path)

Генерирует URL статического ресурса по пути к его файлу.

unverified_path(conn_or_socket_or_endpoint_or_uri, router, path, params \\ %{})

Возвращает путь с соответствующими префиксами имени скрипта без проверки.

unverified_url(conn_or_socket_or_endpoint_or_uri, path, params \\ %{})

Возвращает URL конечной точки, сформированный из пути, без проверки.

url(sigil_p)

Генерирует URL маршрутизатора с проверкой маршрута.

url(conn_or_socket_or_endpoint_or_uri, sigil_p)

Генерирует URL маршрутизатора с проверкой маршрута на основе соединения, сокета или URI.

url(conn_or_socket_or_endpoint_or_uri, router, sigil_p)

Генерирует URL с проверкой маршрута на основе соединения, сокета или URI и маршрутизатора.

Типы

formatted_route()Исходный код

@type formatted_route() :: %{verb: String.t(), path: String.t(), label: String.t()}

plug_opts()Исходный код

@type plug_opts() :: any()

Обратные вызовы

formatted_routes(plug_opts)Исходный код

@callback formatted_routes(plug_opts()) :: [formatted_route()]

Возвращает необходимую информацию о маршрутах для отображения в mix phx.routes.

Параметр plug_opts обычно передаётся только в том случае, если маршрутизатор подключён внутри Phoenix.Router. В противном случае по умолчанию используется [].

verified_route?(plug_opts, list)Исходный код

@callback verified_route?(plug_opts(), [String.t()]) :: boolean()

Возвращает true, если путь проверен, и false в противном случае.

Параметр plug_opts обычно передаётся только в том случае, если маршрутизатор подключён внутри Phoenix.Router. В противном случае по умолчанию используется [].

Функции

path(conn_or_socket_or_endpoint_or_uri, sigil_p)Исходный код

Генерирует путь маршрутизатора с проверкой маршрута.

Дополнительные сведения см. в разделе sigil_p/2.

Выдаёт предупреждение, если указанный путь не соответствует маршрутизатору, заданному в use Phoenix.VerifiedRoutes или атрибуте модуля @router.

Примеры

import Phoenix.VerifiedRoutes

redirect(to: path(conn, ~p"/users/top"))

redirect(to: path(conn, ~p"/users/#{@user}"))

~H"""
<.link href={path(@uri, "/users?page=#{@page}")}>profile</.link>
<.link href={path(@uri, "/users?#{@params}")}>profile</.link>
"""

path(conn_or_socket_or_endpoint_or_uri, router, sigil_p)Исходный код

Генерирует путь маршрутизатора с проверкой маршрута.

Дополнительные сведения см. в разделе sigil_p/2.

Выдаёт предупреждение, если указанный путь не соответствует маршрутизатору, заданному аргументом router.

Примеры

import Phoenix.VerifiedRoutes

redirect(to: path(conn, MyAppWeb.Router, ~p"/users/top"))

redirect(to: path(conn, MyAppWeb.Router, ~p"/users/#{@user}"))

~H"""
<.link href={path(@uri, MyAppWeb.Router, "/users?page=#{@page}")}>profile</.link>
<.link href={path(@uri, MyAppWeb.Router, "/users?#{@params}")}>profile</.link>
"""

sigil_p(route, extra)Исходный код

Генерирует путь маршрутизатора с проверкой маршрута.

Интерполируемые именованные параметры кодируются с помощью протокола Phoenix.Param.

Выдаёт предупреждение, если указанный путь не соответствует маршрутизатору, заданному в use Phoenix.VerifiedRoutes или атрибуте модуля @router.

Примеры

use Phoenix.VerifiedRoutes, endpoint: MyAppWeb.Endpoint, router: MyAppWeb.Router

redirect(to: ~p"/users/top")

redirect(to: ~p"/users/#{@user}")

~H"""
<.link href={~p"/users?page=#{@page}"}>profile</.link>

<.link href={~p"/users?#{@params}"}>profile</.link>
"""

static_integrity(conn_or_socket_or_endpoint, path)Исходный код

Генерирует хеш целостности статического ресурса по пути к его файлу.

Дополнительные сведения см. в разделе Phoenix.Endpoint.static_integrity/1.

Примеры

iex> static_integrity(conn, "/assets/js/app.js")
"813dfe33b5c7f8388bccaaa38eec8382"

iex> static_integrity(socket, "/assets/js/app.js")
"813dfe33b5c7f8388bccaaa38eec8382"

iex> static_integrity(AppWeb.Endpoint, "/assets/js/app.js")
"813dfe33b5c7f8388bccaaa38eec8382"

static_path(conn_or_socket_or_endpoint_or_uri, path)Исходный код

Генерирует путь к статическому ресурсу по пути к его файлу.

Дополнительные сведения см. в разделе Phoenix.Endpoint.static_path/1.

Примеры

iex> static_path(conn, "/assets/js/app.js")
"/assets/js/app-813dfe33b5c7f8388bccaaa38eec8382.js"

iex> static_path(socket, "assets/js/app.js")
"/assets/js/app-813dfe33b5c7f8388bccaaa38eec8382.js"

iex> static_path(AppWeb.Endpoint, "assets/js/app.js")
"/assets/js/app-813dfe33b5c7f8388bccaaa38eec8382.js"

iex> static_path(%URI{path: "/subresource"}, "/assets/js/app.js")
"/subresource/assets/js/app-813dfe33b5c7f8388bccaaa38eec8382.js"

static_url(conn_or_socket_or_endpoint, path)Исходный код

Генерирует URL статического ресурса по пути к его файлу.

Дополнительные сведения см. в разделах Phoenix.Endpoint.static_url/0 и Phoenix.Endpoint.static_path/1.

Примеры

iex> static_url(conn, "/assets/js/app.js")
"https://example.com/assets/js/app-813dfe33b5c7f8388bccaaa38eec8382.js"

iex> static_url(socket, "/assets/js/app.js")
"https://example.com/assets/js/app-813dfe33b5c7f8388bccaaa38eec8382.js"

iex> static_url(AppWeb.Endpoint, "/assets/js/app.js")
"https://example.com/assets/js/app-813dfe33b5c7f8388bccaaa38eec8382.js"

unverified_path(conn_or_socket_or_endpoint_or_uri, router, path, params \\ %{})Исходный код

Возвращает путь с соответствующими префиксами имени скрипта без проверки.

Примеры

iex> unverified_path(conn, AppWeb.Router, "/posts")
"/posts"

iex> unverified_path(conn, AppWeb.Router, "/posts", page: 1)
"/posts?page=1"

unverified_url(conn_or_socket_or_endpoint_or_uri, path, params \\ %{})Исходный код

Возвращает URL конечной точки, сформированный из пути, без проверки.

Примеры

iex> unverified_url(conn, "/posts")
"https://example.com/posts"

iex> unverified_url(conn, "/posts", page: 1)
"https://example.com/posts?page=1"

url(sigil_p)Исходный код

Генерирует URL маршрутизатора с проверкой маршрута.

Дополнительные сведения см. в разделе sigil_p/2.

Выдаёт предупреждение, если указанный путь не соответствует маршрутизатору, заданному в use Phoenix.VerifiedRoutes или атрибуте модуля @router.

Примеры

use Phoenix.VerifiedRoutes, endpoint: MyAppWeb.Endpoint, router: MyAppWeb.Router

redirect(to: url(conn, ~p"/users/top"))

redirect(to: url(conn, ~p"/users/#{@user}"))

~H"""
<.link href={url(@uri, "/users?#{[page: @page]}")}>profile</.link>
"""

Маршрутизатор также можно указать, если требуется проверять маршруты для маршрутизатора, отличного от переданного в use Phoenix.VerifiedRoutes:

redirect(to: url(conn, OtherRouter, ~p"/users"))

Перенаправленные маршруты также разрешаются автоматически. Например, предположим, что в главном маршрутизаторе у вас есть путь перенаправления к маршрутизатору администратора:

defmodule AppWeb.Router do
  ...
  forward "/admin", AppWeb.AdminRouter
end

defmodule AppWeb.AdminRouter do
  ...
  get "/users", AppWeb.Admin.UserController
end

Пути перенаправления в главном маршрутизаторе приложения будут проверяться как обычно, например ~p"/admin/users".

url(conn_or_socket_or_endpoint_or_uri, sigil_p)Исходный код

Генерирует URL маршрутизатора с проверкой маршрута на основе соединения, сокета или URI.

Дополнительные сведения см. в разделе url/1.

url(conn_or_socket_or_endpoint_or_uri, router, sigil_p)Исходный код

Генерирует URL с проверкой маршрута на основе соединения, сокета или URI и маршрутизатора.

Дополнительные сведения см. в разделе url/1.

Пакет Hex Предпросмотр Hex Скачать версию ePub

Создано с помощью ExDoc (v0.40.3) для языка программирования Elixir

© 2014 Chris McCord
Licensed under the MIT License.
https://phoenix.hexdocs.pm/Phoenix.VerifiedRoutes.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API