Spec-Zone.ru › Phoenix

Phoenix.Controller

Исходный код

Контроллеры используются для группировки общей функциональности в одном (подключаемом) модуле.

Например, маршрут:

get "/users/:id", MyAppWeb.UserController, :show

вызовет действие show/2 в MyAppWeb.UserController:

defmodule MyAppWeb.UserController do
  use MyAppWeb, :controller

  def show(conn, %{"id" => id}) do
    user = Repo.get(User, id)
    render(conn, :show, user: user)
  end
end

Действие — это обычная функция, которая получает соединение и параметры запроса в качестве аргументов. Соединение — это структура Plug.Conn, определённая библиотекой Plug.

Затем мы вызываем render/3, передавая соединение, шаблон для отображения (обычно названный в соответствии с действием) и user: user в качестве assigns. Далее мы рассмотрим все эти понятия.

Соединение

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

Эти функции импортируются из двух модулей:

  • Plug.Conn — набор низкоуровневых функций для работы с соединением

  • Phoenix.Controller — функции, предоставляемые Phoenix для поддержки отображения и других специфичных для Phoenix возможностей

Если вам нужны функции для управления соединением без полной реализации контроллера, можно импортировать оба модуля напрямую вместо use Phoenix.Controller.

Отображение

Одна из основных возможностей контроллеров — согласование содержимого и отображение шаблонов на основе информации, отправленной клиентом.

В контроллере можно отображать содержимое двумя способами. Один из вариантов — вызвать функции для конкретного формата, например html/2 и json/2.

Однако чаще всего контроллеры вызывают пользовательские модули, называемые представлениями. Представления — это модули, способные отображать пользовательский формат. Для этого при определении контроллера указывается параметр :formats:

use Phoenix.Controller, formats: [:html, :json]

Теперь при вызове render/3 контроллер с именем MyAppWeb.UserController будет вызывать соответственно MyAppWeb.UserHTML и MyAppWeb.UserJSON при отображении каждого формата:

def show(conn, %{"id" => id}) do
  user = Repo.get(User, id)
  # Will invoke UserHTML.show(%{user: user}) for html requests
  # Will invoke UserJSON.show(%{user: user}) for json requests
  render(conn, :show, user: user)
end

Можно также указать форматы для отображения, напрямую вызвав put_view/2 с соединением. Например, вместо того чтобы выводить имена представлений из контроллера, как в этом примере:

use Phoenix.Controller, formats: [:html, :json]

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

put_view(conn, html: MyAppWeb.UserHTML, json: MyAppWeb.UserJSON)

Или в качестве plug:

plug :put_view, html: MyAppWeb.UserHTML, json: MyAppWeb.UserJSON

Макеты

Во многих приложениях есть общее содержимое, которое нужно включать на каждую страницу, чаще всего тег <head> и его содержимое. В Phoenix это делается с помощью функции put_root_layout:

put_root_layout(conn, html: {MyAppWeb.Layouts, :root})

В большинстве приложений она вызывается как Plug в маршрутизаторе приложения:

plug :put_root_layout, html: {MyAppWeb.Layouts, :root}

Этот макет используется всеми контроллерами, а также Phoenix.LiveView.

Однако можно также задать отдельные макеты для контроллеров с помощью put_layout/2, хотя в Phoenix v1.8 такой подход не рекомендуется: вместо него следует использовать функциональные компоненты для построения приложения.

Параметры

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

  • :formats — форматы, которые этот контроллер будет отображать по умолчанию. Например, указание formats: [:html, :json] для контроллера с именем MyAppWeb.UserController приведёт к вызову MyAppWeb.UserHTML и MyAppWeb.UserJSON при отображении соответствующих форматов.

Параметр :formats обязателен. Если вы не планируете заранее отображать какие-либо форматы, его можно задать пустым списком. Чтобы сохранить поведение предыдущих версий Phoenix, можно явно добавить суффикс "View" к параметру :formats:

use Phoenix.Controller, formats: [html: "View", json: "View"]

Конвейер Plug

Как и маршрутизаторы, контроллеры имеют собственный конвейер Plug. Однако, в отличие от маршрутизаторов, у контроллеров только один конвейер:

defmodule MyAppWeb.UserController do
  use MyAppWeb, :controller

  plug :authenticate, usernames: ["jose", "eric", "sonny"]

  def show(conn, params) do
    # authenticated users only
  end

  defp authenticate(conn, options) do
    if get_session(conn, :username) in options[:usernames] do
      conn
    else
      conn |> redirect(to: "/") |> halt()
    end
  end
end

Plug :authenticate будет вызван перед действием. Если plug вызывает Plug.Conn.halt/1 (который по умолчанию импортируется в контроллеры), конвейер остановится, а действие вызвано не будет.

Защитные условия

plug/2 в контроллерах поддерживает защитные условия, позволяя разработчику настроить plug так, чтобы он выполнялся только для определённого действия.

plug :do_something when action in [:show, :edit]

Из-за приоритета операторов в Elixir, если второй аргумент — это список ключевых слов, при использовании when список ключевых слов нужно заключить в [...]:

plug :authenticate, [usernames: ["jose", "eric", "sonny"]] when action in [:show, :edit]
plug :authenticate, [usernames: ["admin"]] when not action in [:index]

Первый plug будет выполняться только для действий show или edit. Второй plug будет выполняться всегда, кроме действия index.

Эти защитные условия работают как обычные защитные условия Elixir. Единственные переменные, доступные в условии, — это conn, action в виде атома и controller в виде alias.

Контроллеры — это plug

Как и маршрутизаторы, контроллеры являются plug, но они настроены на вызов определённой функции, называемой действием.

Например, маршрут:

get "/users/:id", UserController, :show

вызовет UserController как plug:

UserController.call(conn, :show)

это запустит конвейер plug, который в итоге вызовет внутренний plug действия, перенаправляющий выполнение к функции show/2 в UserController.

Поскольку контроллеры являются plug, они реализуют и init/1, и call/2. Кроме того, они предоставляют функцию с именем action/2, которая после выполнения стека plug отвечает за вызов соответствующего действия (её также можно переопределить).

Переопределение action/2 для пользовательских аргументов

Phoenix добавляет в контроллер plug action/2, который вызывает функцию, сопоставленную маршрутизатором. По умолчанию ей передаются conn и params. В некоторых случаях переопределение plug action/2 в контроллере — удобный способ передавать аргументы в действия, которые иначе пришлось бы каждый раз извлекать из соединения. Например, представьте, что вы сохранили conn.assigns.current_user в соединении и хотите быстро получать доступ к пользователю в каждом действии контроллера:

def action(conn, _) do
  args = [conn, conn.params, conn.assigns.current_user]
  apply(__MODULE__, action_name(conn), args)
end

def index(conn, _params, user) do
  videos = Repo.all(user_videos(user))
  # ...
end

def delete(conn, %{"id" => id}, user) do
  video = Repo.get!(user_videos(user), id)
  # ...
end

Сводка

Типы

layout()
view()

Функции

accepts(conn, accepted)

Согласует содержимое на основе доступных форматов.

action_fallback(plug)

Регистрирует plug, который будет вызван в качестве резервного варианта для действия контроллера.

action_name(conn)

Возвращает имя действия в виде атома; вызывает исключение, если оно недоступно.

allow_jsonp(conn, opts \\ [])

Plug, который может преобразовать ответ JSON в ответ JSONP.

assign(conn, keyword_or_map_or_fun)

Добавляет к соединению несколько пар ключ-значение. Принимает список ключевых слов, карту или функцию с одним аргументом.

clear_flash(conn)

Очищает все flash-сообщения.

controller_module(conn)

Возвращает модуль контроллера в виде атома; вызывает исключение, если он недоступен.

current_path(conn)

Возвращает путь текущего запроса с параметрами запроса по умолчанию

current_path(conn, params)

Возвращает текущий путь с указанными параметрами запроса.

current_url(conn)

Возвращает URL текущего запроса с параметрами запроса по умолчанию

current_url(conn, params)

Возвращает URL текущего запроса с параметрами запроса.

delete_csrf_token()

Удаляет токен CSRF из словаря процесса.

endpoint_module(conn)

Возвращает модуль конечной точки в виде атома; вызывает исключение, если он недоступен.

fetch_flash(conn, opts \\ [])

Извлекает хранилище flash-сообщений.

get_csrf_token()

Получает или создаёт токен CSRF.

get_flash(conn) устарело

Возвращает карту ранее заданных flash-сообщений или пустую карту.

get_flash(conn, key) устарело

Возвращает сообщение из flash по key (или nil, если для key сообщение отсутствует).

get_format(conn)

Возвращает формат запроса, например "json" или "html".

html(conn, data)

Отправляет ответ HTML.

json(conn, data)

Отправляет ответ JSON.

layout(conn, format \\ nil)

Возвращает текущий макет для указанного формата.

merge_flash(conn, enumerable)

Объединяет карту с flash-сообщениями.

protect_from_forgery(conn, opts \\ [])

Включает защиту от CSRF-атак.

put_flash(conn, key, message)

Сохраняет значение во flash-хранилище.

put_format(conn, format)

Устанавливает формат в соединении.

put_layout(conn, layout)

Сохраняет макет для отображения.

put_new_layout(conn, layout)

Сохраняет макет для отображения, если он ещё не был сохранён.

put_new_view(conn, formats)

Сохраняет представление для отображения, если оно ещё не было сохранено.

put_root_layout(conn, layout)

Сохраняет корневой макет для отображения.

put_router_url(conn, uri)

Устанавливает строку URL или %URI{} для генерации маршрутов.

put_secure_browser_headers(conn, headers \\ %{})

Устанавливает заголовки, повышающие безопасность браузера.

put_static_url(conn, uri)

Устанавливает URL или %URI{} для генерации URL статических ресурсов.

put_view(conn, formats)

Сохраняет представление для отображения.

redirect(conn, opts)

Отправляет ответ с перенаправлением на указанный URL.

render(conn, template_or_assigns \\ [])

Отображает указанный шаблон или шаблон по умолчанию, определённый текущим действием, с заданными assigns.

render(conn, template, assigns)

Отображает заданные template и assigns на основе информации conn.

root_layout(conn, format \\ nil)

Возвращает текущий корневой макет для указанного формата.

router_module(conn)

Возвращает модуль маршрутизатора в виде атома; вызывает исключение, если он недоступен.

scrub_params(conn, required_key)

Очищает параметры запроса.

send_download(conn, kind, opts \\ [])

Отправляет указанный файл или двоичные данные для скачивания.

status_message_from_template(template)

Формирует сообщение о статусе на основе имени шаблона.

text(conn, data)

Отправляет текстовый ответ.

view_module(conn, format \\ nil)

Возвращает текущее представление для указанного формата.

view_template(conn)

Возвращает в виде строки имя шаблона, отображённого в представлении (или nil, если шаблон не отображался).

Типы

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

@type layout() :: {module(), layout_name :: atom()} | false

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

@type view() :: atom()

Функции

accepts(conn, accepted)Исходный код

@spec accepts(Plug.Conn.t(), [binary()]) :: Plug.Conn.t()

Выполняет согласование содержимого на основе доступных форматов.

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

Если запрос содержит параметр "_format", он считается форматом, запрошенным клиентом. Если параметр "_format" отсутствует, эта функция анализирует заголовок "accept" и находит соответствующий формат.

Эта функция полезна, если нужно предоставлять содержимое разных типов (например, JSON и HTML) по одним и тем же маршрутам. Однако, если у вас всегда есть отдельные маршруты, можно также отключить согласование содержимого и просто жестко задать нужный формат в конвейерах маршрутов:

plug :put_format, "html"

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

  • список принимаемых аргументов содержит формат "html"

  • в заголовке accept указано более одного типа медиа, перед которым или после которого стоит тип медиа с подстановочным знаком "*/*"

Эта функция вызывает исключение Phoenix.NotAcceptableError с кодом состояния 406, если сервер не может отправить ответ ни в одном из форматов, ожидаемых клиентом.

Примеры

accepts/2 можно вызвать как функцию:

iex> accepts(conn, ["html", "json"])

или использовать как плаг:

plug :accepts, ["html", "json"]
plug :accepts, ~w(html json)

Пользовательские типы медиа

В приложение Phoenix можно добавить пользовательские типы медиа. Сначала нужно сообщить Plug о новых типах медиа в файле config/config.exs:

config :mime, :types, %{
  "application/vnd.api+json" => ["json-api"]
}

Ключ — это тип медиа, а значение — список форматов, с которыми можно сопоставить этот тип медиа. Например, используя "json-api", вы сможете применять шаблоны с расширением "index.json-api" или принудительно задавать определенный формат в URL, передавая "?_format=json-api".

После этого изменения необходимо перекомпилировать plug:

$ mix deps.clean mime --build
$ mix deps.get

Теперь его можно использовать и в accepts:

plug :accepts, ["html", "json-api"]

action_fallback(plug)Исходный код

Регистрирует плаг, который будет вызываться в качестве резервного обработчика действия контроллера.

Резервный плаг полезен для преобразования распространенных структур данных предметной области в допустимый ответ %Plug.Conn{}. Если действие контроллера не возвращает %Plug.Conn{}, будет вызван указанный плаг, который получит %Plug.Conn{} контроллера в том виде, в каком оно было до вызова действия, а также значение, возвращенное действием контроллера.

Примеры

defmodule MyController do
  use Phoenix.Controller

  action_fallback MyFallbackController

  def show(conn, %{"id" => id}, current_user) do
    with {:ok, post} <- Blog.fetch_post(id),
         :ok <- Authorizer.authorize(current_user, :view, post) do

      render(conn, "show.json", post: post)
    end
  end
end

В приведенном выше примере with используется для сопоставления только с успешно полученной записью и последующей проверкой прав доступа текущего пользователя. Если одно из этих условий не будет выполнено, with не вызовет блок render, а вместо этого вернет несопоставленное значение. Например, предположим, что Blog.fetch_post/2 возвращает {:error, :not_found} или Authorizer.authorize/3 возвращает {:error, :unauthorized}. Если такие структуры данных используются как возвращаемые значения на нескольких границах предметной области, можно создать один резервный модуль для преобразования значения в допустимый ответ. Например, для обработки приведенных выше значений можно написать следующий резервный контроллер:

defmodule MyFallbackController do
  use Phoenix.Controller

  def call(conn, {:error, :not_found}) do
    conn
    |> put_status(:not_found)
    |> put_view(MyErrorView)
    |> render(:"404")
  end

  def call(conn, {:error, :unauthorized}) do
    conn
    |> put_status(:forbidden)
    |> put_view(MyErrorView)
    |> render(:"403")
  end
end

action_name(conn)Исходный код

@spec action_name(Plug.Conn.t()) :: atom()

Возвращает имя действия в виде атома; если оно недоступно, вызывает исключение.

allow_jsonp(conn, opts \\ [])Исходный код

@spec allow_jsonp(Plug.Conn.t(), Keyword.t()) :: Plug.Conn.t()

Плаг, который может преобразовать ответ JSON в JSONP.

Если возвращается ответ JSON, он будет преобразован в JSONP при условии, что в строке запроса присутствует поле callback. По умолчанию для поля callback используется значение "callback", но его можно настроить с помощью параметра callback.

Если callback отсутствует или ответ представлен не в формате JSON, функция ничего не делает.

В имени callback разрешены только буквенно-цифровые символы и символ подчеркивания. В противном случае будет вызвано исключение.

Примеры

# Will convert JSON to JSONP if callback=someFunction is given
plug :allow_jsonp

# Will convert JSON to JSONP if cb=someFunction is given
plug :allow_jsonp, callback: "cb"

assign(conn, keyword_or_map_or_fun)Исходный код

Добавляет к соединению несколько пар ключ-значение. Принимает список ключевых слов, карту или функцию с одним аргументом.

Эта функция принимает карту или список ключевых слов с данными assigns и объединяет их с данными assigns соединения. Она эквивалентна нескольким вызовам Plug.Conn.assign/3.

Если передана функция, она получает текущие данные assigns в качестве аргумента, а ее возвращаемое значение объединяется с текущими данными assigns.

Примеры

assign(conn, name: "Alice", role: :admin)
assign(conn, %{name: "Alice", role: :admin})
assign(conn, fn %{name: name, logo: logo} -> %{title: Enum.join([name, logo], " | ")} end)

clear_flash(conn)Исходный код

Удаляет все flash-сообщения.

controller_module(conn)Исходный код

@spec controller_module(Plug.Conn.t()) :: atom()

Возвращает модуль контроллера в виде атома; если он недоступен, вызывает исключение.

current_path(conn)Исходный код

Возвращает путь текущего запроса с параметрами запроса по умолчанию:

iex> current_path(conn)
"/users/123?existing=param"

См. current_path/2, чтобы переопределить параметры по умолчанию.

Путь нормализуется на основе conn.script_name и conn.path_info. Например, "/foo//bar/" будет преобразован в "/foo/bar". Если нужен исходный путь, используйте вместо этого conn.request_path.

current_path(conn, params)Исходный код

Возвращает текущий путь с указанными параметрами запроса.

Чтобы получить только путь запроса, можно передать пустую карту параметров.

Примеры

iex> current_path(conn)
"/users/123?existing=param"

iex> current_path(conn, %{new: "param"})
"/users/123?new=param"

iex> current_path(conn, %{filter: %{status: ["draft", "published"]}})
"/users/123?filter[status][]=draft&filter[status][]=published"

iex> current_path(conn, %{})
"/users/123"

Путь нормализуется на основе conn.script_name и conn.path_info. Например, "/foo//bar/" будет преобразован в "/foo/bar". Если нужен исходный путь, используйте вместо этого conn.request_path.

current_url(conn)Исходный код

Возвращает URL текущего запроса с параметрами запроса по умолчанию:

iex> current_url(conn)
"https://www.example.com/users/123?existing=param"

См. current_url/2, чтобы переопределить параметры по умолчанию.

current_url(conn, params)Исходный код

Возвращает URL текущего запроса с параметрами запроса.

Путь будет получен из текущего запрошенного пути с помощью current_path/1. Схема, хост и другие параметры будут взяты из конфигурации URL в конечной точке Phoenix. Мы не используем информацию о хосте и схеме из запроса, поскольку большинство приложений работают за прокси, и хост и схема могут не соответствовать тем, к которым обращался клиент. Чтобы получить URL точно в том виде, в каком его запросил клиент, см. Plug.Conn.request_url/1.

Примеры

iex> current_url(conn)
"https://www.example.com/users/123?existing=param"

iex> current_url(conn, %{new: "param"})
"https://www.example.com/users/123?new=param"

iex> current_url(conn, %{})
"https://www.example.com/users/123"

Пользовательская генерация URL

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

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

def current_secure_url(conn, params \\ %{}) do
  current_uri = MyAppWeb.Endpoint.struct_url()
  current_path = Phoenix.Controller.current_path(conn, params)
  Phoenix.VerifiedRoutes.unverified_url(%URI{current_uri | scheme: "https"}, current_path)
end

Однако, если нужно, чтобы все сгенерированные URL всегда использовали заданную схему, хост и т. д., можно воспользоваться put_router_url/2.

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

Удаляет токен CSRF из словаря процесса.

Примечание: токен удаляется только после отправки ответа.

endpoint_module(conn)Исходный код

@spec endpoint_module(Plug.Conn.t()) :: atom()

Возвращает модуль конечной точки в виде атома; если он недоступен, вызывает исключение.

fetch_flash(conn, opts \\ [])Исходный код

Получает хранилище flash.

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

Получает или создает токен CSRF.

Если токен существует, он возвращается; в противном случае он создается и сохраняется в словаре процесса.

get_flash(conn)Исходный код

Эта функция устарела. get_flash/1 устарела. Используйте assigns @flash, предоставляемый плагом :fetch_flash.

Возвращает карту ранее заданных flash-сообщений или пустую карту.

Примеры

iex> get_flash(conn)
%{}

iex> conn = put_flash(conn, :info, "Welcome Back!")
iex> get_flash(conn)
%{"info" => "Welcome Back!"}

get_flash(conn, key)Исходный код

Эта функция устарела. get_flash/2 устарела. Вместо нее используйте Phoenix.Flash.get(@flash, key).

Возвращает сообщение из flash по key (или nil, если сообщение для key отсутствует).

Примеры

iex> conn = put_flash(conn, :info, "Welcome Back!")
iex> get_flash(conn, :info)
"Welcome Back!"

get_format(conn)Исходный код

Возвращает формат запроса, например "json" или "html".

Этот формат используется при отображении шаблона, заданного атомом. Например, render(conn, :foo) отобразит "foo.FORMAT", где формат будет тем, который задан здесь. Формат по умолчанию обычно определяется согласованием, выполняемым в accepts/2.

html(conn, data)Исходный код

@spec html(Plug.Conn.t(), iodata()) :: Plug.Conn.t()

Отправляет ответ HTML.

Примеры

iex> html(conn, "<html><head>...")

json(conn, data)Исходный код

@spec json(Plug.Conn.t(), term()) :: Plug.Conn.t()

Отправляет ответ JSON.

Функция использует настроенный :json_library в приложении :phoenix, чтобы :json мог выбрать модуль кодировщика.

Примеры

iex> json(conn, %{id: 123})

layout(conn, format \\ nil)Исходный код

@spec layout(Plug.Conn.t(), binary() | nil) :: {atom(), String.t() | atom()} | false

Получает текущий макет для указанного формата.

Если формат не указан, используется текущий формат соединения.

merge_flash(conn, enumerable)Исходный код

Объединяет карту с flash.

Возвращает обновленное соединение.

Примеры

iex> conn = merge_flash(conn, info: "Welcome Back!")
iex> Phoenix.Flash.get(conn.assigns.flash, :info)
"Welcome Back!"

protect_from_forgery(conn, opts \\ [])Исходный код

Включает защиту от CSRF.

В настоящее время служит оберткой для Plug.CSRFProtection и главным образом используется как функциональный плаг в YourApp.Router.

Информацию о получении и удалении токенов CSRF см. в разделах get_csrf_token/0 и delete_csrf_token/0.

put_flash(conn, key, message)Исходный код

Сохраняет значение во flash.

key может быть атомом или двоичной строкой. Phoenix не ограничивает набор ключей, сохраняемых во flash, если значения согласованы между собой. По умолчанию генераторы Phoenix используют ключи :info и :error.

Возвращает обновленное соединение.

Примеры

iex> conn = put_flash(conn, :info, "Welcome Back!")
iex> Phoenix.Flash.get(conn.assigns.flash, :info)
"Welcome Back!"

put_format(conn, format)Исходный код

Задает формат в соединении.

Этот формат используется при отображении шаблона, заданного атомом. Например, render(conn, :foo) отобразит "foo.FORMAT", где формат будет тем, который задан здесь. Формат по умолчанию обычно определяется согласованием, выполняемым в accepts/2.

Чтобы получить формат, см. get_format/1.

put_layout(conn, layout)Исходный код

@spec put_layout(Plug.Conn.t(), [{format :: atom(), layout()}] | false) ::
  Plug.Conn.t()

Сохраняет макет для отображения.

Макет необходимо задать в виде списка ключевых слов, где ключ — формат запроса, для которого будет применяться макет (например, :html), а значение — одно из следующих:

  • {module, layout}, где module указывает, в каком месте определен макет, а имя layout задано атомом

  • false, что отключает макет

Если false задан без формата, все макеты отключаются.

Примеры

iex> layout(conn)
false

iex> conn = put_layout(conn, html: {AppView, :application})
iex> layout(conn)
{AppView, :application}

iex> conn = put_layout(conn, html: {AppView, :print})
iex> layout(conn)
{AppView, :print}

Вызывает исключение Plug.Conn.AlreadySentError, если conn уже отправлен.

put_new_layout(conn, layout)Исходный код

@spec put_new_layout(Plug.Conn.t(), [{format :: atom(), layout()}] | layout()) ::
  Plug.Conn.t()

Сохраняет макет для отображения, если он еще не был сохранен.

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

Вызывает исключение Plug.Conn.AlreadySentError, если conn уже отправлен.

put_new_view(conn, formats)Исходный код

@spec put_new_view(Plug.Conn.t(), [{format :: atom(), view()}] | view()) ::
  Plug.Conn.t()

Сохраняет представление для отображения, если оно еще не было сохранено.

Вызывает исключение Plug.Conn.AlreadySentError, если conn уже отправлен.

put_root_layout(conn, layout)Исходный код

@spec put_root_layout(Plug.Conn.t(), [{format :: atom(), layout()}] | false) ::
  Plug.Conn.t()

Сохраняет корневой макет для отображения.

Макет необходимо задать в виде списка ключевых слов, где ключ — формат запроса, для которого будет применяться макет (например, :html), а значение — одно из следующих:

  • {module, layout}, где module указывает, в каком месте определен макет, а имя layout задано атомом

  • layout вместо имени макета. Для этого необходимо предварительно задать макет указанного формата в виде {module, layout}

  • false, что отключает макет

Примеры

iex> root_layout(conn)
false

iex> conn = put_root_layout(conn, html: {AppView, :root})
iex> root_layout(conn)
{AppView, :root}

iex> conn = put_root_layout(conn, html: :bare)
iex> root_layout(conn)
{AppView, :bare}

Вызывает исключение Plug.Conn.AlreadySentError, если conn уже отправлен.

put_router_url(conn, uri)Исходный код

Задает строку URL или %URI{} для генерации маршрутов.

Эта функция переопределяет генерацию URL по умолчанию, которая берется из конфигурации конечной точки %Plug.Conn{}.

Примеры

Предположим, что приложение настроено для работы на "example.com", но после входа пользователя нужно, чтобы все ссылки использовали "some_user.example.com". Для этого можно задать соответствующую конфигурацию URL маршрутизатора:

def put_router_url_by_user(conn) do
  put_router_url(conn, get_user_from_conn(conn).account_name <> ".example.com")
end

Теперь при вызове Routes.some_route_url(conn, ...) будет использоваться URL маршрутизатора, заданный выше. Обратите внимание: если нужно создавать маршруты для текущего домена, предпочтительно использовать вспомогательные функции Routes.some_route_path, поскольку они всегда формируют относительные ссылки.

put_secure_browser_headers(conn, headers \\ %{})Исходный код

Добавляет заголовки, повышающие безопасность браузера.

Задаются следующие заголовки, если они еще не заданы:

  • content-security-policy — задает frame-ancestors и base-uri в значение self, ограничивая встраивание и использование элемента <base> только тем же источником соответственно. Это эквивалентно заданию "base-uri 'self'; frame-ancestors 'self';"

  • referrer-policy — отправлять источник только для междоменных запросов

  • x-content-type-options — задает значение nosniff. Для этого необходимо отправлять теги script и style с правильным типом содержимого

  • x-permitted-cross-domain-policies — задает значение none, чтобы ограничить доступ Adobe Flash Player к данным

Также можно передать карту пользовательских заголовков, которая будет объединена со значениями по умолчанию.

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

put_static_url(conn, uri)Исходный код

Задает URL или %URI{} для генерации URL статических ресурсов.

Использование этой функции для структуры %Plug.Conn{} сообщает static_url/2 использовать указанную информацию для генерации URL вместо конфигурации конечной точки %Plug.Conn{} (аналогично put_router_url/2, но для статических URL).

put_view(conn, formats)Исходный код

@spec put_view(Plug.Conn.t(), [{format :: atom(), view()}] | view()) :: Plug.Conn.t()

Сохраняет представление для отображения.

Вызывает исключение Plug.Conn.AlreadySentError, если conn уже отправлен.

Примеры

iex> put_view(conn, html: AppHTML, json: AppJSON)

redirect(conn, opts)Исходный код

Отправляет ответ перенаправления на указанный URL.

В целях безопасности :to принимает только пути. Используйте параметр :external, чтобы перенаправить на любой URL.

Ответ будет отправлен с кодом состояния, заданным в соединении с помощью Plug.Conn.put_status/2. Если код состояния не задан, отправляется ответ 302.

Примеры

iex> redirect(conn, to: "/login")

iex> redirect(conn, external: "https://elixir-lang.org")

render(conn, template_or_assigns \\ [])Исходный код

@spec render(Plug.Conn.t(), Keyword.t() | map() | binary() | atom()) :: Plug.Conn.t()

Отображает указанный шаблон или шаблон по умолчанию, заданный текущим действием, с указанными данными assigns.

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

render(conn, template, assigns)Исходный код

@spec render(Plug.Conn.t(), binary() | atom(), Keyword.t() | map()) :: Plug.Conn.t()

Отображает указанный template и assigns на основе информации conn.

После отображения шаблона его формат задается в качестве типа содержимого ответа (например, для HTML-шаблона тип содержимого ответа будет "text/html"), а данные отправляются клиенту с кодом состояния 200 по умолчанию.

Аргументы

  • conn — структура Plug.Conn

  • template — атом или строка. Если передан атом, например :index, будет отображен шаблон с тем же форматом, что и формат, возвращенный функцией get_format/1. Например, для HTML-запроса будет отображен шаблон "index.html". Если шаблон задан строкой, в ней также должно присутствовать расширение, например "index.json"

  • assigns — словарь с данными assigns, которые будут использоваться в представлении. Эти данные assigns объединяются с данными assigns соединения и имеют более высокий приоритет (conn.assigns)

Примеры

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

defmodule MyAppWeb.UserController do
  # Will use MyAppWeb.UserHTML and MyAppWeb.UserJSON
  use Phoenix.Controller, formats: [:html, :json]
end

После задания форматов можно отобразить шаблон двумя способами. Первый — передать строку с именем шаблона и явно указать формат:

def show(conn, _params) do
  render(conn, "show.html", message: "Hello")
end

В приведенном выше примере отображается шаблон "show.html" из MyAppWeb.UserHTML, а тип содержимого ответа задается как "text/html".

Чтобы формат шаблона задавался динамически на основе запроса, можно передать вместо этого атом (без расширения):

def show(conn, _params) do
  render(conn, :show, message: "Hello")
end

Если форматы неизвестны во время компиляции, можно вызвать put_view/2 во время выполнения:

defmodule MyAppWeb.UserController do
  use Phoenix.Controller

  def show(conn, _params) do
    conn
    |> put_view(html: MyAppWeb.UserHTML)
    |> render("show.html", message: "Hello")
  end
end

root_layout(conn, format \\ nil)Исходный код

@spec root_layout(Plug.Conn.t(), binary() | nil) ::
  {atom(), String.t() | atom()} | false

Получает текущий корневой макет для указанного формата.

Если формат не указан, используется текущий формат соединения.

router_module(conn)Исходный код

@spec router_module(Plug.Conn.t()) :: atom()

Возвращает модуль маршрутизатора в виде атома; если он недоступен, вызывает исключение.

scrub_params(conn, required_key)Исходный код

@spec scrub_params(Plug.Conn.t(), String.t()) :: Plug.Conn.t()

Очищает параметры запроса.

Этот процесс состоит из двух этапов:

  • Проверяет наличие required_key
  • Заменяет пустые параметры со значением required_key (рекурсивно) на nil

Эта функция полезна для удаления пустых строк, отправленных через HTML-формы. Если вы предоставляете API, скорее всего, вызывать scrub_params/2 не нужно.

Если required_key отсутствует, будет вызвано исключение Phoenix.MissingParamError.

Примеры

iex> scrub_params(conn, "user")

send_download(conn, kind, opts \\ [])Источник

Отправляет указанный файл или двоичные данные в виде загрузки.

Второй аргумент должен быть {:binary, contents}, где contents будет отправлен в виде загрузки, или {:file, path}, где path — расположение файла для отправки в файловой системе. Не подставляйте путь из внешних параметров, так как это может позволить перемещаться по файловой системе.

Загрузка выполняется путем установки "content-disposition" в значение attachment. "content-type" также устанавливается на основе расширения указанного имени файла, но его можно настроить с помощью параметров :content_type и :charset.

Параметры

  • :filename — имя файла, отображаемое пользователю при загрузке
  • :content_type — тип содержимого файла или двоичных данных, отправляемых для загрузки. Он автоматически определяется по расширению имени файла
  • :disposition — задает тип расположения (:attachment или :inline). Если используется :attachment, пользователю будет предложено сохранить файл. Если используется :inline, браузер попытается открыть файл. По умолчанию — :attachment.
  • :charset — кодировка файла, например "utf-8". По умолчанию не задана
  • :offset — количество байтов, на которое нужно сместиться при чтении. По умолчанию — 0
  • :length — общее количество байтов для чтения. По умолчанию — :all
  • :encode — кодирует имя файла с помощью URI.encode/2. По умолчанию — true. Если задано false, кодирование отключается. При отключении кодирования необходимо убедиться, что в имени файла нет специальных символов, например кавычек, символов новой строки и т. д. В противном случае приложение может подвергнуться атакам

Примеры

Чтобы отправить файл, хранящийся в каталоге priv вашего приложения:

path = Application.app_dir(:my_app, "priv/prospectus.pdf")
send_download(conn, {:file, path})

При использовании {:file, path} имя файла определяется по указанному пути, но его также можно задать явно.

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

send_download(conn, {:binary, "world"}, filename: "hello.txt")

См. Plug.Conn.send_file/3 и Plug.Conn.send_resp/3, если вы хотите получить доступ к низкоуровневым функциям Plug, используемым для отправки файлов и ответов.

status_message_from_template(template)Источник

Создает сообщение о статусе на основе имени шаблона.

Примеры

iex> status_message_from_template("404.html")
"Not Found"
iex> status_message_from_template("whatever.html")
"Internal Server Error"

text(conn, data)Источник

@spec text(Plug.Conn.t(), String.Chars.t()) :: Plug.Conn.t()

Отправляет текстовый ответ.

Примеры

iex> text(conn, "hello")

iex> text(conn, :implements_to_string)

view_module(conn, format \\ nil)Источник

@spec view_module(Plug.Conn.t(), binary() | nil) :: atom()

Возвращает текущее представление для указанного формата.

Если формат не указан, используется текущий формат соединения.

view_template(conn)Источник

@spec view_template(Plug.Conn.t()) :: binary() | nil

Возвращает имя шаблона, отрисованного в представлении, в виде строки (или nil, если шаблон не был отрисован).

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

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

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

Spec-Zone.ru

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