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

request-modification.mddocs/

Request Modification

Comprehensive request modification capabilities allowing you to transform headers, body content, and HTTP options before the request is proxied to the target server.

Capabilities

Request Options Decorator

Modify HTTP request options before issuing the proxy request. This includes headers, method, and other HTTP client options.

/**
 * Modify request options before sending proxy request
 * @param {object} proxyReqOpts - HTTP request options object
 * @param {object} srcReq - Original Express request object
 * @returns {object|Promise<object>} Modified request options
 */
proxyReqOptDecorator: (proxyReqOpts, srcReq) => object | Promise<object>;

Usage Examples:

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

// Modify headers and method
app.use('/api', proxy('backend.example.com', {
  proxyReqOptDecorator: function(proxyReqOpts, srcReq) {
    // Add authentication header
    proxyReqOpts.headers['Authorization'] = 'Bearer ' + srcReq.user.token;
    
    // Add custom headers
    proxyReqOpts.headers['X-Client-ID'] = 'web-app';
    proxyReqOpts.headers['X-Request-ID'] = generateRequestId();
    
    // Modify content type
    proxyReqOpts.headers['Content-Type'] = 'application/json';
    
    // Change HTTP method if needed
    if (srcReq.method === 'PATCH') {
      proxyReqOpts.method = 'PUT';
    }
    
    return proxyReqOpts;
  }
}));

// Remove sensitive headers
app.use('/external', proxy('external-api.com', {
  proxyReqOptDecorator: function(proxyReqOpts, srcReq) {
    // Remove internal headers before forwarding
    delete proxyReqOpts.headers['x-internal-user-id'];
    delete proxyReqOpts.headers['x-session-token'];
    
    // Add API key for external service
    proxyReqOpts.headers['X-API-Key'] = process.env.EXTERNAL_API_KEY;
    
    return proxyReqOpts;
  }
}));

Promise-Based Request Options

Use Promises for asynchronous request option modification.

/**
 * Promise-based request options decorator
 * @param {object} proxyReqOpts - HTTP request options object
 * @param {object} srcReq - Original Express request object
 * @returns {Promise<object>} Promise resolving to modified request options
 */
proxyReqOptDecorator: (proxyReqOpts, srcReq) => Promise<object>;

Usage Examples:

// Async token refresh
app.use('/secured', proxy('secure-api.com', {
  proxyReqOptDecorator: async function(proxyReqOpts, srcReq) {
    // Refresh token if needed
    const token = await authService.getValidToken(srcReq.user.id);
    proxyReqOpts.headers['Authorization'] = `Bearer ${token}`;
    
    return proxyReqOpts;
  }
}));

// Database-driven configuration
app.use('/tenant', proxy('multi-tenant.example.com', {
  proxyReqOptDecorator: function(proxyReqOpts, srcReq) {
    return new Promise(async (resolve, reject) => {
      try {
        const tenantConfig = await db.getTenantConfig(srcReq.headers['x-tenant-id']);
        
        // Apply tenant-specific headers
        proxyReqOpts.headers['X-Tenant-Key'] = tenantConfig.apiKey;
        proxyReqOpts.headers['X-Tenant-Region'] = tenantConfig.region;
        
        resolve(proxyReqOpts);
      } catch (error) {
        reject(error);
      }
    });
  }
}));

Request Body Decorator

Modify the request body before sending the proxy request. Supports various data types and transformations.

/**
 * Modify request body before sending proxy request
 * @param {any} bodyContent - Original request body content
 * @param {object} srcReq - Original Express request object
 * @returns {any|Promise<any>} Modified body content
 */
proxyReqBodyDecorator: (bodyContent, srcReq) => any | Promise<any>;

Usage Examples:

// JSON transformation
app.use('/transform', proxy('backend.example.com', {
  proxyReqBodyDecorator: function(bodyContent, srcReq) {
    if (srcReq.headers['content-type']?.includes('application/json')) {
      const data = JSON.parse(bodyContent.toString());
      
      // Add metadata to request
      data.metadata = {
        timestamp: new Date().toISOString(),
        source: 'web-proxy',
        userAgent: srcReq.headers['user-agent']
      };
      
      // Transform field names
      if (data.user_id) {
        data.userId = data.user_id;
        delete data.user_id;
      }
      
      return JSON.stringify(data);
    }
    
    return bodyContent;
  }
}));

// String manipulation
app.use('/text', proxy('text-processor.com', {
  proxyReqBodyDecorator: function(bodyContent, srcReq) {
    // Reverse string content (example transformation)
    return bodyContent.toString().split('').reverse().join('');
  }
}));

Promise-Based Body Modification

Use Promises for asynchronous body transformation operations.

/**
 * Promise-based request body decorator
 * @param {any} bodyContent - Original request body content
 * @param {object} srcReq - Original Express request object
 * @returns {Promise<any>} Promise resolving to modified body content
 */
proxyReqBodyDecorator: (bodyContent, srcReq) => Promise<any>;

Usage Examples:

// Async data enrichment
app.use('/enrich', proxy('data-service.com', {
  proxyReqBodyDecorator: async function(bodyContent, srcReq) {
    const data = JSON.parse(bodyContent.toString());
    
    // Enrich with external data
    if (data.userId) {
      const userProfile = await userService.getProfile(data.userId);
      data.userProfile = userProfile;
    }
    
    return JSON.stringify(data);
  }
}));

// External service integration
app.use('/validate', proxy('validator.example.com', {
  proxyReqBodyDecorator: function(bodyContent, srcReq) {
    return new Promise((resolve, reject) => {
      // Validate with external service
      externalValidator.validate(bodyContent.toString())
        .then(validatedData => {
          resolve(validatedData);
        })
        .catch(error => {
          reject(new Error('Validation failed: ' + error.message));
        });
    });
  }
}));

Important Notes

Path Limitation

Note that req.path cannot be changed via proxyReqOptDecorator. Use proxyReqPathResolver for path modifications instead.

Body Parser Compatibility

When using with body-parser middleware:

// Correct order: proxy BEFORE body-parser
app.use('/proxy', proxy('example.com'));
app.use(bodyParser.json()); // Declare AFTER proxy

// If you must use proxy after body-parser:
app.use(bodyParser.json());
app.use('/proxy', proxy('example.com', {
  parseReqBody: false,  // Important: disable parsing
  proxyReqBodyDecorator: function(bodyContent, srcReq) {
    // Explicitly specify the body to send
    return JSON.stringify(srcReq.body);
  }
}));

Deprecated Options

decorateRequest (Removed)

The decorateRequest option has been removed. Use proxyReqOptDecorator and proxyReqBodyDecorator instead.

/**
 * @deprecated REMOVED - Use proxyReqOptDecorator and proxyReqBodyDecorator instead
 * @throws {Error} Will throw an error if used
 */
decorateRequest?: Function;