Skip to content
This repository was archived by the owner on Jul 17, 2026. It is now read-only.

Body parsing

Eugene Lazutkin edited this page Apr 19, 2026 · 1 revision

Body parsing

The adapter handles request bodies in two modes, picked automatically per request.

Decision flow

Is req.body defined?
├─ Yes → use it as-is (body-parser middleware already handled parsing)
└─ No  → stream req, enforce maxBodyBytes, JSON.parse the result

Pre-parsed body (recommended)

Most Express apps use the built-in express.json() parser for other routes. When req.body !== undefined, the adapter uses that value directly.

app.use(express.json({limit: '2mb'}));
app.use('/planets', createExpressAdapter(planets));

In this mode the body parser's own size cap applies; the adapter's maxBodyBytes is not consulted. This keeps the body-size policy in one place (the middleware chain), which is usually what you want.

Advantages:

  • One place to configure JSON parsing (including non-JSON content types if you need them).
  • Other middleware downstream / upstream can inspect / transform the body.
  • Consistent req.body shape across all routes.

Stream-parsed body (fallback)

If no body parser is installed, the adapter consumes req (the raw Node IncomingMessage — Express's Request extends it) directly, enforces a byte cap, and JSON.parses the result. Rejected on cap overflow or malformed JSON.

app.use(createExpressAdapter(planets, {maxBodyBytes: 256 * 1024}));

Useful when:

  • Your app is small enough that a body parser isn't worth wiring.
  • You want per-adapter body-size policy (e.g. a bulk-load endpoint accepts 16 MiB while everything else caps at 64 KiB).
  • You want to stay zero-deps beyond what's strictly required.

Default cap: 1048576 (1 MiB).

Error responses

Condition Status code
Body exceeds maxBodyBytes 413 PayloadTooLarge
Body is not valid JSON 400 BadJsonBody
Body is missing required shape 400 BadLoadBody

BadLoadBody specifically fires on PUT /-load when the body isn't an array.

Mixing modes in one app

You can run multiple adapters with different body-cap policies:

app.use(express.json({limit: '256kb'}));                       // default for most routes
app.use('/planets', createExpressAdapter(planets));            // uses pre-parsed body (256 KiB cap)
app.use('/bulk',    createExpressAdapter(bulk, {              // but pre-parsed means the express.json cap applies —
  maxBodyBytes: 16 * 1024 * 1024                              // `maxBodyBytes` here is ignored as long as
})));                                                          // express.json ran first.

If you need per-route body-size policy, mount the bulk adapter before the global body parser, or scope the body parser to specific routes using app.use(path, middleware).

// Bulk route streams its own body (no express.json upstream → maxBodyBytes kicks in).
app.use('/bulk', createExpressAdapter(bulk, {maxBodyBytes: 16 * 1024 * 1024}));
// Everything else uses the shared parser.
app.use(express.json({limit: '256kb'}));
app.use('/planets', createExpressAdapter(planets));

Why we don't call req.destroy() on overflow

Some stream-parsers destroy the underlying socket when they see an over-cap body, to prevent the client from uploading more. This adapter does not — the socket needs to stay alive so Express can write the 413 response. Backpressure plus the aborted flag stop the reader from buffering; the response completes normally; the connection closes via the framework's standard response-end path.

The worst case is a few kernel-buffer bytes per over-sized request — negligible compared to letting the framework respond.

Reading the raw stream ourselves

The stream reader is a small utility exposed under dynamodb-toolkit-express/read-body.js:

import {readJsonBody} from 'dynamodb-toolkit-express/read-body.js';

// Elsewhere in your Express app:
const body = await readJsonBody(req, 1024 * 1024);

Normally you won't need this — the adapter handles it internally. It's exported so consumers can reuse the same cap-enforced JSON reader in unrelated routes or when writing their own middleware for edge cases.

Clone this wiki locally