# `MishkaCmsCore.Runtime.Plugs.RawBody`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core/runtime/plugs/raw_body.ex#L5)

The bytes a webhook was sent, kept for its signature check.

A webhook is signed over its body exactly as it was sent — Svix (Resend), Stripe and GitHub all
sign that way — and `Plug.Parsers` reads the body to decode it, so a route behind the endpoint
sees only the decoded params. One decoded and encoded again is a different text and never matches.

Give the endpoint's parsers this body reader:

    plug Plug.Parsers,
      parsers: [:urlencoded, :multipart, :json],
      pass: ["*/*"],
      json_decoder: Phoenix.json_library(),
      body_reader: {MishkaCmsCore.Runtime.Plugs.RawBody, :read_body, []}

A request whose path starts with `/webhooks/` then keeps its body in `conn.private[:raw_body]`
(`raw_body/1`) beside the params, and every other request is read as Plug reads it and keeps
nothing. An extension mounts its webhooks under that prefix — `/webhooks/<extension>/<sender>` —
through `MishkaCmsCore.ExtensionRouter`'s `:api` routes.

The parsers' own `:length` limit applies, so a body is never kept past what they would read. A
request whose content type no parser reads is not read at all, and keeps nothing: its route reads
it with `Plug.Conn.read_body/2`.

# `prefix`

```elixir
@spec prefix() :: String.t()
```

The path prefix whose requests keep their body.

# `raw_body`

```elixir
@spec raw_body(Plug.Conn.t()) :: binary() | nil
```

The body a webhook request was sent, or `nil` when it was not kept.

# `read_body`

```elixir
@spec read_body(Plug.Conn.t(), keyword()) ::
  {:ok, binary(), Plug.Conn.t()}
  | {:more, binary(), Plug.Conn.t()}
  | {:error, term()}
```

`Plug.Conn.read_body/2`, keeping what it reads when the request is a webhook's. For
`Plug.Parsers`' `:body_reader`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
