# `Apical.Plugs.RequestBody.Source`
[🔗](https://github.com/E-xyza/Apical/blob/main/lib/apical/plugs/request_body/_source.ex#L1)

Behaviour for adapters that process request bodies and alter the conn.

# `marshal_context`

```elixir
@type marshal_context() :: map() | nil
```

Type for marshal context that contains type information for marshalling
request body values from strings to their proper types.

# `validator`

```elixir
@type validator() :: nil | {module(), atom()} | {module(), atom(), keyword()}
```

Type for a function that encapsulates the logic for validating a request body.

The function should return `:ok` if the body is valid, or `{:error, keyword}`

In the generic case, keyword should contain the key `:message` which determines
what the request body error message will be.

For more specific cases, see the documentation for `Exonerate` which describes
the fields available.

The default validator (if no validation is to be performed) will return `:ok`
on any input.

# `fetch`

```elixir
@callback fetch(Plug.Conn.t(), validator(), marshal_context(), opts :: keyword()) ::
  {:ok, Plug.Conn.t()} | {:error, keyword()}
```

Fetches and processes the request body.

The marshal_context parameter contains type information extracted from the schema
that can be used to convert string values to their proper types (e.g., "42" to 42).

# `validate!`

```elixir
@callback validate!(subschema :: map(), operation_id :: String.t()) :: :ok
```

Compile-time check to see if the validator is valid for the given requestBody
subschema.

This may reject for any reason and should raise a CompileError if the validator
cannot be used for that subschema.

# `fetch_body`

```elixir
@spec fetch_body(
  Plug.Conn.t(),
  keyword()
) :: {:ok, body :: iodata(), Plug.Conn.t()} | {:error, any()}
```

Utility function that grabs request bodies.

`Apical.Plugs.RequestBody.Source` modules are expected to use this function
if they need the request body, since it conforms to the options keyword that
plug uses natively.  This function will exhaust the ability of the `conn` to
have its body fetched.  Thus, the use of this function is *not* required

> ### Streaming request bodies {: .warning }
>
> If the request body source plugin processes data in a streaming fashion, this
> function should not be used, instead manually call `Plug.Conn.read_body/2`
> in your plugin's `c:fetch/3` function

### options

`:length` (integer, default `8_000_000`) - total maximum length of the request body.
`:read_length` (integer, default `1_000_000`) - maximum length of each chunk.
`:string` (boolean, default `false`) - if true, the result will be a single binary,
  if false, the result *may* be an improper iolist.

---

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