# `Accrue.Webhook.CachingBodyReader`
[🔗](https://github.com/szTheory/accrue/blob/accrue-v0.3.1/lib/accrue/webhook/caching_body_reader.ex#L1)

Custom body reader for `Plug.Parsers` that tees the raw body into
`conn.assigns[:raw_body]` for webhook signature verification.

Only used inside the `:accrue_webhook_raw_body` pipeline (D2-20) --
never globally. This ensures that non-webhook routes are unaffected
by raw-body capture (WH-01).

## Usage

    pipeline :accrue_webhook_raw_body do
      plug Plug.Parsers,
        parsers: [:json],
        pass: ["*/*"],
        json_decoder: Jason,
        body_reader: {Accrue.Webhook.CachingBodyReader, :read_body, []},
        length: 1_000_000
    end

## Implementation

Chunks are prepended (O(1) cons) during streaming reads and reversed
at flatten time in the consuming plug. This avoids quadratic binary
concatenation when the body arrives in multiple chunks.

# `read_body`

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

Reads the request body and tees it into `conn.assigns[:raw_body]`.

Returns `{:ok, body, conn}`, `{:more, body, conn}`, or `{:error, reason}`
matching the `Plug.Conn.read_body/2` contract expected by `Plug.Parsers`.

---

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