Modify proxy responses before sending them to the client. This includes transforming response data, modifying headers, and handling various content types including JSON, text, and binary data.
Modify the proxy response data before sending it to the client. This function receives the complete response and allows full transformation.
/**
* Modify response data before sending to client
* @param {object} proxyRes - The proxy response object
* @param {any} proxyResData - The response data from the proxy
* @param {object} userReq - The original user request
* @param {object} userRes - The user response object
* @returns {any|Promise<any>} Modified response data
*/
userResDecorator: (proxyRes, proxyResData, userReq, userRes) => any | Promise<any>;Usage Examples:
const proxy = require('express-http-proxy');
// JSON response transformation
app.use('/api', proxy('backend.example.com', {
userResDecorator: function(proxyRes, proxyResData, userReq, userRes) {
// Parse JSON response
const data = JSON.parse(proxyResData.toString('utf8'));
// Add metadata
data.metadata = {
processedAt: new Date().toISOString(),
proxy: true,
version: '2.1.1'
};
// Transform field names
if (data.user_id) {
data.userId = data.user_id;
delete data.user_id;
}
return JSON.stringify(data);
}
}));
// Filter sensitive data
app.use('/users', proxy('user-service.com', {
userResDecorator: function(proxyRes, proxyResData, userReq, userRes) {
const users = JSON.parse(proxyResData.toString('utf8'));
// Remove sensitive fields
const sanitizedUsers = users.map(user => ({
id: user.id,
name: user.name,
email: user.email
// Remove: password, ssn, internal_notes, etc.
}));
return JSON.stringify(sanitizedUsers);
}
}));Use Promises for asynchronous response transformation operations.
/**
* Promise-based response decorator
* @param {object} proxyRes - The proxy response object
* @param {any} proxyResData - The response data from the proxy
* @param {object} userReq - The original user request
* @param {object} userRes - The user response object
* @returns {Promise<any>} Promise resolving to modified response data
*/
userResDecorator: (proxyRes, proxyResData, userReq, userRes) => Promise<any>;Usage Examples:
// Async data enrichment
app.use('/products', proxy('product-service.com', {
userResDecorator: async function(proxyRes, proxyResData, userReq, userRes) {
const products = JSON.parse(proxyResData.toString('utf8'));
// Enrich each product with additional data
const enrichedProducts = await Promise.all(
products.map(async (product) => ({
...product,
reviews: await reviewService.getReviews(product.id),
inventory: await inventoryService.getStock(product.id)
}))
);
return JSON.stringify(enrichedProducts);
}
}));
// External service integration
app.use('/translate', proxy('content-service.com', {
userResDecorator: function(proxyRes, proxyResData, userReq, userRes) {
return new Promise((resolve, reject) => {
const content = JSON.parse(proxyResData.toString('utf8'));
// Translate content if needed
if (userReq.headers['accept-language']?.startsWith('es')) {
translationService.translate(content, 'es')
.then(translatedContent => {
resolve(JSON.stringify(translatedContent));
})
.catch(reject);
} else {
resolve(JSON.stringify(content));
}
});
}
}));Modify response headers before sending to the client. This decorator replaces (rather than merges) the headers.
/**
* Modify response headers before sending to client
* @param {object} headers - The response headers object
* @param {object} userReq - The original user request
* @param {object} userRes - The user response object
* @param {object} proxyReq - The proxy request object
* @param {object} proxyRes - The proxy response object
* @returns {object} Modified headers object
*/
userResHeaderDecorator: (headers, userReq, userRes, proxyReq, proxyRes) => object;Usage Examples:
// Security headers
app.use('/secure', proxy('secure-api.com', {
userResHeaderDecorator: function(headers, userReq, userRes, proxyReq, proxyRes) {
// Add security headers
headers['X-Frame-Options'] = 'DENY';
headers['X-Content-Type-Options'] = 'nosniff';
headers['X-XSS-Protection'] = '1; mode=block';
// Remove internal headers
delete headers['x-internal-server'];
delete headers['x-debug-info'];
// Add CORS headers if needed
if (userReq.headers.origin) {
headers['Access-Control-Allow-Origin'] = userReq.headers.origin;
headers['Access-Control-Allow-Credentials'] = 'true';
}
return headers;
}
}));
// Caching headers
app.use('/static', proxy('cdn.example.com', {
userResHeaderDecorator: function(headers, userReq, userRes, proxyReq, proxyRes) {
// Set appropriate caching headers
if (proxyRes.statusCode === 200) {
headers['Cache-Control'] = 'public, max-age=3600';
headers['ETag'] = `"${Date.now()}"`;
}
// Add custom headers
headers['X-Served-By'] = 'express-http-proxy';
headers['X-Response-Time'] = Date.now() - userReq.startTime;
return headers;
}
}));If the proxy response is gzipped, express-http-proxy automatically:
userResDecoratorThis behavior cannot currently be disabled.
When the proxied service returns 304 Not Modified, the userResDecorator step is skipped since there is no body to process.
userResDecorator and userResHeaderDecoratorWhile the proxyRes, userReq, and userRes arguments are passed by reference and can be modified, this is not a reliable interface and may be removed in future versions. Use the appropriate decorators for modifications.
// Handle errors in response processing
app.use('/error-prone', proxy('unreliable-service.com', {
userResDecorator: function(proxyRes, proxyResData, userReq, userRes) {
try {
const data = JSON.parse(proxyResData.toString('utf8'));
return JSON.stringify(data);
} catch (error) {
// Return error response or original data
console.error('Response processing error:', error);
return JSON.stringify({ error: 'Response processing failed' });
}
}
}));The intercept option has been deprecated. Use userResDecorator instead.
/**
* @deprecated Use userResDecorator instead
*/
intercept?: (proxyRes, proxyResData, userReq, userRes, callback) => void;Migration Example:
// Old intercept usage
app.use('/old', proxy('example.com', {
intercept: function(proxyRes, proxyResData, userReq, userRes, cb) {
const data = JSON.parse(proxyResData.toString('utf8'));
data.newProperty = 'exciting data';
cb(null, JSON.stringify(data));
}
}));
// New userResDecorator usage
app.use('/new', proxy('example.com', {
userResDecorator: function(proxyRes, proxyResData, userReq, userRes) {
const data = JSON.parse(proxyResData.toString('utf8'));
data.newProperty = 'exciting data';
return JSON.stringify(data);
}
}));