1.1 KiB · text 5af55d9
defmodule GitGudWeb.Plugs.CacheRawBody do
@moduledoc """
Body reader for `Plug.Parsers` that caches the raw bytes on
`conn.assigns[:raw_body]`.
HTTP signature verification needs the exact bytes sent on the wire
*and* we want the JSON-parsed body. Without this, `Plug.Parsers`
consumes the body and verification has nothing to hash. Wire as:
plug Plug.Parsers,
parsers: [...],
body_reader: {GitGudWeb.Plugs.CacheRawBody, :read_body, []}
"""
def read_body(conn, opts) do
case Plug.Conn.read_body(conn, opts) do
{:ok, body, conn} ->
{:ok, body, append(conn, body)}
{:more, body, conn} ->
{:more, body, append(conn, body)}
{:error, _} = err ->
err
end
end
defp append(conn, chunk) do
existing = conn.assigns[:raw_body] || []
Plug.Conn.assign(conn, :raw_body, [existing, chunk])
end
@doc "Final raw body as a binary, or nil if none was read."
def get(conn) do
case conn.assigns[:raw_body] do
nil -> nil
iodata -> IO.iodata_to_binary(iodata)
end
end
end