# @marblejs/middleware-body

## Installation

```bash
yarn add @marblejs/middleware-body
```

Requires `@marblejs/core` to be installed.

## Importing

```typescript
import { bodyParser$ } from '@marblejs/middleware-body';
```

## Type declaration <a href="#type-declaration" id="type-declaration"></a>

```haskell
bodyParser$ :: BodyParserOptions -> HttpMiddlewareEffect
```

## Parameters

| parameter | definition                      |
| --------- | ------------------------------- |
| *options* | \<optional> `BodyParserOptions` |

***BodyParserOptions***

| ***parameter*** | definition                      |
| --------------- | ------------------------------- |
| *parser*        | \<optional> `RequestBodyParser` |
| *type*          | \<optional> `Array<string>`     |

The `type` option is used to determine what media type the middleware will parse. It is passed directly to the [type-is](https://www.npmjs.org/package/type-is#readme) library and this can be an extension name (like `json`), a mime type (like `application/json`), or a mime type with a wildcard (like `*/*` or `*/json`). Defaults to `*/*`.

## Basic usage

{% code title="app.ts" %}

```typescript
import { bodyParser$ } from '@marblejs/middleware-body';

export default httpListener({
  middlewares: [bodyParser$()],
  effects: [/* ... */],
});
```

{% endcode %}

Lets assume that we have the following *CURL* command, which triggers `POST /api/login` endpoint:

```bash
$ curl --header "Content-Type: application/json" \
  --request POST \
  --data '{ "username": "foo", "password": "bar" }' \
  http://localhost:3000/api/login
```

Using previously connected `bodyParser$` middleware, the app will intercept the following payload object:

```typescript
req.body = {
  username: 'foo',
  password: 'bar',
};
```

The *POST* request body can be intercepted like follows.

{% code title="login.effect.ts" %}

```typescript
import { r } from '@marblejs/core';

export const login$ = r.pipe(
  r.matchPath('/login'),
  r.matchType('POST'),
  r.useEffect(req$ => req$.pipe(
    map(req => req.body as { username: string, password: string }),
    map(body => ({ body: `Hello, ${body.username}!` }))
  )));
```

{% endcode %}

{% hint style="danger" %}
All properties and values in `req.body` object are untrusted (unknown) and should be validated before trusting.
{% endhint %}

{% hint style="info" %}
This middleware does not handle multipart bodies.
{% endhint %}

## Advanced usage

The middleware does nothing if request *Content-Type* is not matched, which makes a possibility for chaining multiple parsers one after another. For example, we can register multiple middlewares that will parse only a certain set of possible *Content-Type* headers.

**Default parser:**

```typescript
import { bodyParser$ } from '@marblejs/middleware-body';

bodyparser$();
```

Parses *application/json* (to JSON), *application/x-www-form-urlencoded* (to JSON), *application/octet-stream* (to Buffer) and *text/plain* (to string) content types

**JSON parser:**

```typescript
import { bodyParser$, jsonParser } from '@marblejs/middleware-body';

bodyParser$({
  parser: jsonParser,
  type: ['*/json', 'application/vnd.api+json'],
})
```

Parses `req.body` to JSON object.

**URLEncoded parser:**

```typescript
import { bodyParser$, urlEncodedParser } from '@marblejs/middleware-body';

bodyParser$({
  parser: urlEncodedParser,
  type: ['*/x-www-form-urlencoded'],
});
```

Parses encoded URLs `req.body` to JSON object.

**Text parser:**

```typescript
import { bodyParser$, textParser } from '@marblejs/middleware-body';

bodyParser$({
  parser: textParser,
  type: ['text/*'],
});
```

Parses `req.body` to string.

**Raw parser:**

```typescript
import { bodyParser$, rawParser } from '@marblejs/middleware-body';

bodyParser$({
  parser: rawParser,
  type: ['application/octet-stream'],
}),
```

Parses `req.body` to Buffer.

## Custom parsers

If the available parsers are not enough, you can create your own body parsers by conforming to `RequestBodyParser` interface. The example below shows how the `jsonParser` looks underneath.

```typescript
export const jsonParser: RequestBodyParser = req => body =>
  JSON.parse(body.toString());
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://marblejs.gitbook.io/docs/other/api-reference/middleware-body.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
