в файле endpoint.ex добавьте специальное устройство чтения тела и свой пользовательский плагин в следующем порядке:
plug Api.Plug.PrepareParse # should be called before Plug.Parsers
plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
body_reader: {CacheBodyReader, :read_body, []}, # CacheBodyReader option is also needed
json_decoder: Phoenix.json_library()
Определите пользовательское устройство чтения тела
defmodule CacheBodyReader do
def read_body(conn, _opts) do
# Actual implementation
# {:ok, body, conn} = Plug.Conn.read_body(conn, opts)
# conn = update_in(conn.assigns[:raw_body], &[body | (&1 || [])])
# {:ok, body, conn}
{:ok, conn.assigns.raw_body, conn}
end
end
Затем Ваш пользовательский анализ подготовки
defmodule Api.Plug.PrepareParse do
import Plug.Conn
@env Application.get_env(:application_api, :env)
@methods ~w(POST PUT PATCH PUT)
def init(opts) do
opts
end
def call(conn, opts) do
%{method: method} = conn
if method in @methods and not (@env in [:test]) do
case Plug.Conn.read_body(conn, opts) do
{:error, :timeout} ->
raise Plug.TimeoutError
{:error, _} ->
raise Plug.BadRequestError
{:more, _, conn} ->
# raise Plug.PayloadTooLargeError, conn: conn, router: __MODULE__
error = %{message: "Payload too large error"}
render_error(conn, error)
{:ok, "" = body, conn} ->
body = "{}" // otherwise error
update_in(conn.assigns[:raw_body], &[body | &1 || []])
{:ok, body, conn} ->
case Jason.decode(body) do
{:ok, _result} ->
update_in(conn.assigns[:raw_body], &[body | &1 || []])
{:error, _reason} ->
error = %{message: "Malformed JSON in the body"}
render_error(conn, error)
end
end
else
conn
end
end
def render_error(conn, error) do
conn
|> put_resp_header("content-type", "application/json; charset=utf-8")
|> send_resp(400, Jason.encode!(error))
|> halt
end
end
Несколько ссылок:
- https://elixirforum.com/t/how-to-read-request-body-multiple-times-during-request-handling/3845
- https://elixirforum.com/t/how-do-you-put-a-request-body-in-a-plug-conn/8584
- https://elixirforum.com/t/write-malformed-json-in-the-body-plug/30578