Comprehensive request modification capabilities allowing you to transform headers, body content, and HTTP options before the request is proxied to the target server.
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;
}
}));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);
}
});
}
}));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('');
}
}));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));
});
});
}
}));Note that req.path cannot be changed via proxyReqOptDecorator. Use proxyReqPathResolver for path modifications instead.
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);
}
}));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;