Как получить тело запроса в phoenix?

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

Выполняя обратный инжиниринг, я получил следующий код:

defmodule MyApp.Controllers.Pages do
  use Phoenix.Controller

  def post(conn) do
    {_, {_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, body, _, _, _, _, _, _}} = conn.adapter
    text conn, "#{inspect body}"
  end
end

с маршрутизацией:

defmodule MyApp.Router do
  use Phoenix.Router

  post "/test", MyApp.Controllers.Pages, :post
end

Должен быть лучший способ, не так ли?

Ожидаемое поведение:

curl -XPOST localhost:4000/test -d 'this is a test'
$ "this is a test"

person Uri Agassi    schedule 08.06.2014    source источник


Ответы (4)


Я использую Phoenix версии 0.6.1, и мне не удалось заставить работать описанные выше подходы. Однако я нашел следующее для работы:

defmodule MyApp.MyController do
  use Phoenix.Controller

  plug :action 

  def login(conn, _params) do
    {:ok, data, _conn_details} = Plug.Conn.read_body(conn)

    # ...
  end
end

Тело запроса возвращается в виде данных. Не уверен, что это «официальный» способ получить тело запроса, но решил поделиться им.

person Rachel Bowyer    schedule 21.12.2014

Я только что выпустил Phoenix 0.2.5 с возможностью легкого доступа к телу запроса. Плагин 4.4 был только что выпущен для поддержки collect_body(conn, ""). Эта функция импортируется в контексте ваших контроллеров Phoenix, поэтому вы сможете просто получить все тело в виде строки, используя collect_body(conn, ""). Пожалуйста, сделайте это и откройте проблему Github, если вы не можете заставить ее работать.

https://github.com/elixir-lang/plug/blob/master/lib/plug/conn.ex#L355-L394

person Chris McCord    schedule 11.06.2014
comment
К сожалению, я не могу протестировать Phoenix 0.2.5, так как в моем проекте используется amnesia, который ломается на elixir 0.14.0... - person Uri Agassi; 12.06.2014

Я нашел это в тестах в язык эликсира:

defmodule MyApp.Controllers.Pages do
  use Phoenix.Controller

  def post(conn) do
    body = read_req_body(conn)
    text conn, "#{inspect body}"
  end

  defp read_req_body({:ok, buffer, state}, acc, adapter) do
    read_req_body(adapter.stream_req_body(state, 100_000), acc <> buffer, adapter)
  end

  defp read_req_body({:done, state}, acc, _adapter) do
    {acc, state}
  end

  defp read_req_body(%{adapter: {adapter, state}}) do
    {body, _} = read_req_body({:ok, "", state}, "", adapter)
    body
  end
end
person Uri Agassi    schedule 08.06.2014

Вам нужно использовать функцию read_body.

Эта функция считывает часть тела запроса до заданной длины. Если данных для чтения больше, возвращается {:more, partial_body, conn}. В противном случае возвращается {:ok, body, conn}. В случае ошибки при чтении сокета возвращается {:error, Reason} согласно :gen_tcp.recv/2.

Справочник

person Farshid Ashouri    schedule 08.09.2016