NextRush
API ReferenceMiddleware

@nextrush/body-parser

Parse JSON, URL-encoded, text, and raw request bodies with size limits and security protections.

Parse incoming request bodies before your handlers process them.

HTTP request bodies arrive as raw byte streams. This middleware reads, validates, and parses them into usable JavaScript values — handling JSON, URL-encoded forms, plain text, and raw binary data. Built-in protections guard against oversized payloads, prototype pollution, and malformed input.


Default Behavior

With default options, bodyParser() parses JSON and URL-encoded request bodies. Text and raw binary parsing stay off until you enable them.

Bodyless HTTP methods (GET, HEAD, DELETE, OPTIONS) are skipped automatically. If the body has already been parsed by another middleware, parsing is skipped.


Installation

$ pnpm add @nextrush/body-parser

Minimal Usage

import { createApp } from '@nextrush/core';
import { bodyParser } from '@nextrush/body-parser';

const app = createApp();

// Parses JSON and URL-encoded bodies by default
app.use(bodyParser());

app.use(async (ctx) => {
  ctx.json({ received: ctx.body });
});

Individual Parsers

Use individual parsers when you need to handle specific content types only.

import { json } from '@nextrush/body-parser';

app.use(json());
// Parses: application/json
import { urlencoded } from '@nextrush/body-parser';

app.use(urlencoded());
// Parses: application/x-www-form-urlencoded
import { text } from '@nextrush/body-parser';

app.use(text());
// Parses: text/plain
import { raw } from '@nextrush/body-parser';

app.use(raw());
// Parses: application/octet-stream

Configuration Options

bodyParser(options?)

Combined parser that routes to the appropriate parser based on Content-Type.

function bodyParser(options?: BodyParserOptions): BodyParserMiddleware;

Options

PropertyTypeDescription
jsonJsonOptions | false= {}JSON parser options, or false to disable
urlencodedUrlEncodedOptions | false= {}URL-encoded parser options, or false to disable
textTextOptions | false= undefinedText parser options — disabled by default
rawRawOptions | false= undefinedRaw parser options — disabled by default

JSON and URL-encoded parsing are enabled by default. To enable text or raw parsing, provide an options object (even {} activates them). To disable a parser, set it to false.

app.use(
  bodyParser({
    json: { limit: '10mb', strict: true },
    urlencoded: { extended: true, depth: 5 },
    text: {}, // Enable text parsing with defaults
    raw: false, // Explicitly disable raw parsing
  })
);

Multipart requests (multipart/form-data) throw an UNSUPPORTED_CONTENT_TYPE error with a hint to use a dedicated multipart parser.

json(options?)

function json(options?: JsonOptions): BodyParserMiddleware;

JSON Options

PropertyTypeDescription
limitnumber | string= '1mb' (1,048,576 bytes)Maximum body size in bytes or as a string with unit
strictboolean= trueAccept only objects and arrays — rejects primitives
typestring | string[]= ['application/json']Content-Type(s) to match
rawBodyboolean= falseStore raw Buffer on ctx.rawBody
reviver?JsonReviverCustom reviver passed to JSON.parse()
maxDepth?numberMaximum JSON nesting depth — rejects deeper payloads after parsing
verify?VerifyCallbackCallback invoked with raw buffer before parsing — throw to reject

urlencoded(options?)

function urlencoded(options?: UrlEncodedOptions): BodyParserMiddleware;

URL-Encoded Options

PropertyTypeDescription
limitnumber | string= '100kb' (102,400 bytes)Maximum body size in bytes or as a string with unit
extendedboolean= trueEnable nested object parsing (e.g. user[name]=John)
parameterLimitnumber= 1000Maximum number of parameters accepted
depthnumber= 20Maximum nesting depth for extended parsing
typestring | string[]= ['application/x-www-form-urlencoded']Content-Type(s) to match
rawBodyboolean= falseStore raw Buffer on ctx.rawBody
verify?VerifyCallbackCallback invoked with raw buffer before parsing — throw to reject

text(options?)

function text(options?: TextOptions): BodyParserMiddleware;

Text Options

PropertyTypeDescription
limitnumber | string= '100kb' (102,400 bytes)Maximum body size in bytes or as a string with unit
defaultCharsetSupportedCharset= 'utf-8'Fallback charset when not specified in Content-Type
typestring | string[]= ['text/plain']Content-Type(s) to match
rawBodyboolean= falseStore raw Buffer on ctx.rawBody
verify?VerifyCallbackCallback invoked with raw buffer before parsing — throw to reject

raw(options?)

function raw(options?: RawOptions): BodyParserMiddleware;

Raw Options

PropertyTypeDescription
limitnumber | string= '100kb' (102,400 bytes)Maximum body size in bytes or as a string with unit
typestring | string[]= ['application/octet-stream']Content-Type(s) to match
verify?VerifyCallbackCallback invoked with raw buffer before parsing — throw to reject

Integration Example

An API server with error handling, JSON parsing, and webhook signature verification:

import { createApp } from '@nextrush/core';
import { json, BodyParserError } from '@nextrush/body-parser';
import { createHmac } from 'node:crypto';

const app = createApp();

// Error handler (register before body parser)
app.use(async (ctx, next) => {
  try {
    await next();
  } catch (error) {
    if (error instanceof BodyParserError) {
      ctx.status = error.status;
      ctx.json({ error: error.message, code: error.code });
      return;
    }
    throw error;
  }
});

// Parse JSON with raw body access for webhook verification
app.use(json({ limit: '1mb', rawBody: true }));

app.post('/webhook', async (ctx) => {
  const signature = ctx.headers['x-signature'] as string;
  const rawBody = ctx.rawBody as Buffer;

  const expected = createHmac('sha256', process.env.WEBHOOK_SECRET!).update(rawBody).digest('hex');

  if (signature !== expected) {
    ctx.status = 401;
    ctx.json({ error: 'Invalid signature' });
    return;
  }

  ctx.json({ ok: true });
});

Error Handling

All parsers throw BodyParserError on failure. Each error includes status (HTTP status code), code (machine-readable string), and expose (whether the message is safe for clients).

import { BodyParserError } from '@nextrush/body-parser';

app.use(async (ctx, next) => {
  try {
    await next();
  } catch (error) {
    if (error instanceof BodyParserError) {
      ctx.status = error.status;
      ctx.json({ error: error.message, code: error.code });
      return;
    }
    throw error;
  }
});

Error Codes

CodeStatusCause
ENTITY_TOO_LARGE413Body exceeds configured size limit
INVALID_JSON400JSON syntax error
STRICT_MODE_VIOLATION400JSON value is a primitive in strict mode
JSON_DEPTH_EXCEEDED400JSON nesting depth exceeds maxDepth
INVALID_URLENCODED400Malformed URL-encoded data
TOO_MANY_PARAMETERS413URL-encoded parameter count exceeds parameterLimit
DEPTH_EXCEEDED400URL-encoded nesting exceeds depth limit
INVALID_PARAMETER400Prototype pollution attempt (__proto__, constructor, prototype)
UNSUPPORTED_CHARSET415Charset in Content-Type is not supported
UNSUPPORTED_CONTENT_TYPE415Content type not handled (e.g. multipart/form-data)
BODY_READ_ERROR400Error reading request stream
REQUEST_CLOSED400Connection closed before body was received
REQUEST_ABORTED400Client aborted the request

Common Mistakes

bodyParser() does not parse text or raw bodies by default. Pass text: {} or raw: {} in the options to enable them.

  • Using bodyParser() and expecting text/raw parsing — these are disabled by default. Enable them explicitly: bodyParser({ text: {}, raw: {} }).
  • Setting the wrong size limit units — limits accept 'b', 'kb', 'mb', 'gb'. A bare number is treated as bytes.
  • Expecting multipart form uploads to work — this parser does not handle multipart/form-data. Use a dedicated multipart parser.
  • Forgetting error handling — without an error-catching middleware upstream, BodyParserError will crash your app.

Troubleshooting

ctx.body is undefined after parsing:

  • Verify the request has a matching Content-Type header.
  • Check the HTTP method — GET, HEAD, DELETE, and OPTIONS requests are skipped.
  • Confirm no earlier middleware has already set ctx.body.

413 errors on valid payloads:

  • Increase the limit option. The JSON default is 1mb; URL-encoded, text, and raw default to 100kb.

UNSUPPORTED_CONTENT_TYPE error:

  • The combined parser throws this for multipart/form-data requests. Use a separate multipart parser.

On this page