or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

body-processing.mderror-handling.mdfiltering.mdindex.mdnetwork-configuration.mdpath-resolution.mdrequest-modification.mdresponse-processing.md
tile.json

body-processing.mddocs/

Body Processing Configuration

Control how request bodies are parsed, encoded, and handled during the proxying process. This includes configuration for binary uploads, text encoding, size limits, and compatibility with body-parser middleware.

Capabilities

Parse Request Body

Control whether the proxy middleware parses the request body. This is essential for binary uploads and performance optimization with large payloads.

/**
 * Whether to parse the request body
 * @type {boolean}
 * @default true
 */
parseReqBody?: boolean;

Usage Examples:

const proxy = require('express-http-proxy');

// Disable body parsing for binary uploads
app.use('/upload', proxy('file-server.com', {
  parseReqBody: false // Required for binary uploads
}));

// Default behavior (body parsing enabled)
app.use('/api', proxy('api.example.com', {
  parseReqBody: true // Default value, can be omitted
}));

// Large file handling
app.use('/large-files', proxy('storage.example.com', {
  parseReqBody: false, // Don't hold large files in memory
  limit: '100mb' // This will be ignored when parseReqBody is false
}));

Request as Buffer

Control whether the request body should be encoded as a Node.js Buffer when sending the proxied request.

/**
 * Encode request body as Node Buffer
 * @type {boolean}
 * @default false
 */
reqAsBuffer?: boolean;

Usage Examples:

// Binary data handling
app.use('/binary', proxy('binary-processor.com', {
  reqAsBuffer: true,
  reqBodyEncoding: null // Preserve binary data
}));

// Image upload handling
app.use('/images', proxy('image-service.com', {
  parseReqBody: true,
  reqAsBuffer: true,
  reqBodyEncoding: null // Important for binary image data
}));

Request Body Encoding

Specify the encoding used to decode the request body. This is crucial for handling different types of content correctly.

/**
 * Encoding used to decode request body
 * @type {string|null}
 * @default 'utf-8'
 */
reqBodyEncoding?: string | null;

Usage Examples:

// Default UTF-8 encoding for text
app.use('/text', proxy('text-processor.com', {
  reqBodyEncoding: 'utf-8' // Default value
}));

// Preserve binary data (images, files, etc.)
app.use('/files', proxy('file-handler.com', {
  reqBodyEncoding: null // Preserve as Buffer
}));

// Specific encoding for legacy systems
app.use('/legacy', proxy('legacy-system.com', {
  reqBodyEncoding: 'latin1' // For legacy text encoding
}));

// Binary image uploads
app.use('/images', proxy('image-service.com', {
  parseReqBody: true,
  reqAsBuffer: true,
  reqBodyEncoding: null // Critical for image data
}));

Body Size Limit

Set the maximum allowed size for request bodies. Uses the same format as the bytes.js package.

/**
 * Body size limit
 * @type {string}
 * @default '1mb'
 */
limit?: string;

Usage Examples:

// Small API requests
app.use('/api', proxy('api.example.com', {
  limit: '1mb' // Default value
}));

// Large file uploads
app.use('/upload', proxy('upload-service.com', {
  limit: '50mb' // Allow larger uploads
}));

// Tiny data endpoints
app.use('/tiny', proxy('micro-service.com', {
  limit: '1kb' // Very restrictive
}));

// Video upload service
app.use('/videos', proxy('video-service.com', {
  limit: '500mb',
  parseReqBody: false // Recommended for very large files
}));

Advanced Body Processing Patterns

Binary File Upload Handling

// Complete binary upload configuration
app.use('/upload', proxy('storage-service.com', {
  parseReqBody: false, // Don't parse large binary files
  limit: '100mb', // Set appropriate limit (ignored when parseReqBody is false)
  
  // Handle the raw stream directly
  proxyReqBodyDecorator: function(bodyContent, srcReq) {
    // bodyContent will be the raw stream when parseReqBody is false
    return bodyContent;
  }
}));

Text Content with Custom Encoding

// Legacy system with custom encoding
app.use('/legacy-text', proxy('legacy.example.com', {
  parseReqBody: true,
  reqBodyEncoding: 'latin1',
  reqAsBuffer: false,
  
  proxyReqBodyDecorator: function(bodyContent, srcReq) {
    // Process text with legacy encoding
    const text = bodyContent.toString();
    return text.toUpperCase(); // Example transformation
  }
}));

JSON with Size Validation

// JSON API with custom size limits
app.use('/json-api', proxy('json-service.com', {
  parseReqBody: true,
  reqBodyEncoding: 'utf-8',
  limit: '5mb',
  
  proxyReqBodyDecorator: function(bodyContent, srcReq) {
    try {
      const data = JSON.parse(bodyContent.toString());
      
      // Add validation or transformation
      if (Array.isArray(data) && data.length > 1000) {
        throw new Error('Array too large');
      }
      
      return JSON.stringify(data);
    } catch (error) {
      throw new Error('Invalid JSON: ' + error.message);
    }
  }
}));

Body Parser Compatibility

Correct Middleware Order

const express = require('express');
const bodyParser = require('body-parser');
const proxy = require('express-http-proxy');

const app = express();

// CORRECT: Declare proxy BEFORE body-parser
app.use('/proxy', proxy('example.com'));

// Declare body-parser AFTER proxy
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// Other routes
app.use('/api', otherRoutes);

When Body Parser Must Come First

// If you MUST use proxy after body-parser
const app = express();

// Body parser comes first (unavoidable in some cases)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// Configure proxy to work with pre-parsed body
app.use('/proxy', proxy('example.com', {
  parseReqBody: false, // Critical: don't parse again
  
  proxyReqBodyDecorator: function(bodyContent, srcReq) {
    // Explicitly specify the body to send
    // srcReq.body is already parsed by body-parser
    return JSON.stringify(srcReq.body);
  }
}));

Performance Considerations

Memory Usage

// Memory-efficient configuration for large files
app.use('/efficient', proxy('service.com', {
  parseReqBody: false, // Stream directly, don't buffer
  // limit is ignored when parseReqBody is false
}));

// Memory-intensive configuration (avoid for large files)
app.use('/memory-intensive', proxy('service.com', {
  parseReqBody: true, // Buffers entire body in memory
  limit: '100mb' // Large limit = high memory usage
}));

Streaming vs Buffering

  • parseReqBody: false: Streams request directly to target server (memory efficient)
  • parseReqBody: true: Buffers entire request body in memory (required for modification)

Error Handling

Size Limit Exceeded

When the body size exceeds the limit, express-http-proxy returns a 413 Request Entity Too Large error.

app.use('/protected', proxy('service.com', {
  limit: '1mb'
}));

// Error handling middleware
app.use((error, req, res, next) => {
  if (error.status === 413) {
    res.status(413).json({
      error: 'Request body too large',
      limit: '1mb'
    });
  } else {
    next(error);
  }
});

Encoding Errors

app.use('/safe-encoding', proxy('service.com', {
  reqBodyEncoding: 'utf-8',
  
  proxyReqBodyDecorator: function(bodyContent, srcReq) {
    try {
      // Safe encoding handling
      const text = bodyContent.toString('utf-8');
      return text;
    } catch (error) {
      console.error('Encoding error:', error);
      throw new Error('Invalid character encoding');
    }
  }
}));