Body Parsing
Expediate ships five body-parsing utilities: middleware factories for the most common content types, an auto-detecting catch-all, and a streaming multipart generator.
All body-parsing middleware must be registered before route handlers that read req.body.
Content-type pass-through behaviour
Typed parsers (json(), formData(), formEncoded()) follow Express behaviour: when the request carries a Content-Type that does not match what the parser handles, the parser calls next() and lets subsequent middleware handle the request. This makes it safe to stack parsers globally:
app.use(json()); // handles application/json
app.use(formEncoded()); // handles application/x-www-form-urlencoded
// A request with Content-Type: multipart/form-data passes both and falls throughparseBody() is the strict catch-all — it handles all supported types and returns 415 Unsupported Media Type for anything else.
json()
Parses application/json bodies and populates req.body.
import { json } from 'expediate';
app.use(json());
app.post('/data', (req, res) => {
res.json({ received: (req as any).body });
});| Option | Type | Default | Description |
|---|---|---|---|
limit |
string | number |
'100kb' |
Max body size. Accepts '10kb', '2mb', '1gb', or bytes |
inflate |
boolean |
true |
Accept gzip/deflate encoded bodies |
reviver |
Reviver | null |
null |
Second argument to JSON.parse |
strict |
boolean |
true |
Reserved for future top-level primitive rejection (not yet enforced) |
Error responses:
| Status | Cause |
|---|---|
400 Bad Request |
Malformed JSON or parse error |
413 Content Too Large |
Body exceeds limit |
415 Unsupported Media Type |
Unknown Content-Encoding (e.g. br) |
formData()
Parses multipart/form-data bodies. Populates req.body with an array of FormPart objects:
interface FormPart {
headers: Record<string, string>; // part headers, keys lowercased
content: Buffer; // raw part body
}import { formData } from 'expediate';
app.post('/upload', formData(), (req, res) => {
const parts = (req as any).body as FormPart[];
for (const part of parts) {
const disp = part.headers['content-disposition'];
console.log(disp, '-', part.content.length, 'bytes');
}
res.status(201).end();
});Accepts the same limit and inflate options as json().
formEncoded()
Parses application/x-www-form-urlencoded bodies. Repeated keys produce arrays:
import { formEncoded } from 'expediate';
app.post('/form', formEncoded(), (req, res) => {
const { username, tags } = (req as any).body;
// tags: string | string[] (array when key is repeated)
res.json({ username, tags });
});parseBody()
Auto-detects the Content-Type and dispatches to the appropriate parser.
| Content-Type | Result in req.body |
|---|---|
application/json |
Parsed JS value |
multipart/form-data |
FormPart[] |
application/x-www-form-urlencoded |
Record<string, string | string[]> |
text/plain |
Decoded string |
| Anything else | 415 Unsupported Media Type |
import { parseBody } from 'expediate';
app.use(parseBody()); // handles all four types; 415 for anything elsestreamFormData()
An async generator that yields each multipart/form-data part as a stream, without buffering the entire body first. Ideal for large file uploads.
import { streamFormData } from 'expediate';
import type { FormPartStream } from 'expediate';
app.post('/upload', async (req, res) => {
for await (const part of streamFormData(req)) {
const disp = part.headers['content-disposition'];
// part.stream is a Readable
const chunks: Buffer[] = [];
for await (const chunk of part.stream) chunks.push(chunk);
const content = Buffer.concat(chunks);
console.log(disp, content.length, 'bytes');
}
res.send('ok');
});FormPartStream shape:
interface FormPartStream {
headers: Record<string, string>;
stream: Readable;
}req.json(), req.text(), req.formData()
These are lower-level request methods attached directly to the request object by the router (no middleware needed). They return a Promise and resolve to null when the request has no body.
app.post('/data', async (req, res) => {
const body = await req.json(); // parse as JSON
const text = await req.text(); // read as string
const parts = await req.formData(); // parse as multipart
res.json({ ok: true });
});When a body-parser middleware has already consumed the stream, these methods return the cached req.body value.
Options (BodyOptions)
interface BodyOptions {
limit?: string | number; // default: '100kb'
inflate?: boolean; // default: true — accept gzip/deflate
reviver?: Reviver | null; // default: null — JSON.parse reviver
}Compression support
Request body decompression is controlled by the inflate option (default true). Supported Content-Encoding values:
gzipdeflateidentity(no-op)
Unknown Content-Encoding values produce 415 Unsupported Media Type.
Brotli request decompression (
Content-Encoding: br) is not currently supported.