Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

http-proxy-middleware

Package Overview
Dependencies
Maintainers
1
Versions
88
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

http-proxy-middleware - npm Package Compare versions

Comparing version 2.0.6 to 3.0.0-beta.0

dist/configuration.d.ts

2

dist/errors.d.ts
export declare enum ERRORS {
ERR_CONFIG_FACTORY_TARGET_MISSING = "[HPM] Missing \"target\" option. Example: {target: \"http://www.example.org\"}",
ERR_CONTEXT_MATCHER_GENERIC = "[HPM] Invalid context. Expecting something like: \"/api\" or [\"/api\", \"/ajax\"]",
ERR_CONTEXT_MATCHER_INVALID_ARRAY = "[HPM] Invalid context. Expecting something like: [\"/api\", \"/ajax\"] or [\"/api/**\", \"!**.html\"]",
ERR_CONTEXT_MATCHER_INVALID_ARRAY = "[HPM] Invalid pathFilter. Expecting something like: [\"/api\", \"/ajax\"] or [\"/api/**\", \"!**.html\"]",
ERR_PATH_REWRITER_CONFIG = "[HPM] Invalid pathRewrite config. Expecting object with pathRewrite config or a rewrite function"
}

@@ -8,4 +8,4 @@ "use strict";

ERRORS["ERR_CONTEXT_MATCHER_GENERIC"] = "[HPM] Invalid context. Expecting something like: \"/api\" or [\"/api\", \"/ajax\"]";
ERRORS["ERR_CONTEXT_MATCHER_INVALID_ARRAY"] = "[HPM] Invalid context. Expecting something like: [\"/api\", \"/ajax\"] or [\"/api/**\", \"!**.html\"]";
ERRORS["ERR_CONTEXT_MATCHER_INVALID_ARRAY"] = "[HPM] Invalid pathFilter. Expecting something like: [\"/api\", \"/ajax\"] or [\"/api/**\", \"!**.html\"]";
ERRORS["ERR_PATH_REWRITER_CONFIG"] = "[HPM] Invalid pathRewrite config. Expecting object with pathRewrite config or a rewrite function";
})(ERRORS = exports.ERRORS || (exports.ERRORS = {}));
/// <reference types="node" />
import type * as http from 'http';
import type { Request } from '../types';
/**
* Fix proxied body if bodyParser is involved.
*/
export declare function fixRequestBody(proxyReq: http.ClientRequest, req: http.IncomingMessage): void;
export declare function fixRequestBody(proxyReq: http.ClientRequest, req: Request): void;
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {

@@ -6,0 +10,0 @@ if (k2 === undefined) k2 = k;

@@ -5,2 +5,5 @@ "use strict";

const zlib = require("zlib");
const debug_1 = require("../debug");
const function_1 = require("../utils/function");
const debug = debug_1.Debug.extend('response-interceptor');
/**

@@ -14,3 +17,4 @@ * Intercept responses from upstream.

function responseInterceptor(interceptor) {
return async function proxyRes(proxyRes, req, res) {
return async function proxyResResponseInterceptor(proxyRes, req, res) {
debug('intercept proxy response');
const originalProxyRes = proxyRes;

@@ -26,5 +30,8 @@ let buffer = Buffer.from('', 'utf8');

// call interceptor with intercepted response (buffer)
debug('call interceptor function: %s', (0, function_1.getFunctionName)(interceptor));
const interceptedBuffer = Buffer.from(await interceptor(buffer, originalProxyRes, req, res));
// set correct content-length (with double byte character support)
debug('set content-length: %s', Buffer.byteLength(interceptedBuffer, 'utf8'));
res.setHeader('content-length', Buffer.byteLength(interceptedBuffer, 'utf8'));
debug('write intercepted response');
res.write(interceptedBuffer);

@@ -60,2 +67,3 @@ res.end();

if (decompress) {
debug(`decompress proxy response with 'content-encoding': %s`, contentEncoding);
_proxyRes.pipe(decompress);

@@ -71,2 +79,3 @@ _proxyRes = decompress;

function copyHeaders(originalResponse, response) {
debug('copy original response headers');
response.statusCode = originalResponse.statusCode;

@@ -73,0 +82,0 @@ response.statusMessage = originalResponse.statusMessage;

@@ -1,5 +0,3 @@

import type { Filter, RequestHandler, Options } from './types';
import type { RequestHandler, Options } from './types';
export declare class HttpProxyMiddleware {
private logger;
private config;
private wsInternalSubscribed;

@@ -10,4 +8,5 @@ private serverOnCloseSubscribed;

private pathRewriter;
constructor(context: Filter | Options, opts?: Options);
constructor(options: Options);
middleware: RequestHandler;
private registerPlugins;
private catchUpgradeRequest;

@@ -17,7 +16,2 @@ private handleUpgrade;

* Determine whether request should be proxied.
*
* @private
* @param {String} context [description]
* @param {Object} req [description]
* @return {Boolean}
*/

@@ -36,3 +30,2 @@ private shouldProxy;

private applyPathRewrite;
private logError;
}

@@ -5,11 +5,11 @@ "use strict";

const httpProxy = require("http-proxy");
const config_factory_1 = require("./config-factory");
const contextMatcher = require("./context-matcher");
const handlers = require("./_handlers");
const logger_1 = require("./logger");
const configuration_1 = require("./configuration");
const get_plugins_1 = require("./get-plugins");
const path_filter_1 = require("./path-filter");
const PathRewriter = require("./path-rewriter");
const Router = require("./router");
const debug_1 = require("./debug");
const function_1 = require("./utils/function");
class HttpProxyMiddleware {
constructor(context, opts) {
this.logger = (0, logger_1.getInstance)();
constructor(options) {
this.wsInternalSubscribed = false;

@@ -20,13 +20,14 @@ this.serverOnCloseSubscribed = false;

var _a, _b;
if (this.shouldProxy(this.config.context, req)) {
if (this.shouldProxy(this.proxyOptions.pathFilter, req)) {
try {
const activeProxyOptions = await this.prepareProxyRequest(req);
(0, debug_1.Debug)(`proxy request to target: %O`, activeProxyOptions.target);
this.proxy.web(req, res, activeProxyOptions);
}
catch (err) {
next(err);
next && next(err);
}
}
else {
next();
next && next();
}

@@ -41,6 +42,6 @@ /**

*/
const server = (_b = ((_a = req.socket) !== null && _a !== void 0 ? _a : req.connection)) === null || _b === void 0 ? void 0 : _b.server;
const server = (_b = (((_a = req.socket) !== null && _a !== void 0 ? _a : req.connection))) === null || _b === void 0 ? void 0 : _b.server;
if (server && !this.serverOnCloseSubscribed) {
server.on('close', () => {
this.logger.info('[HPM] server close signal received: closing proxy server');
(0, debug_1.Debug)('server close signal received: closing proxy server');
this.proxy.close();

@@ -57,2 +58,3 @@ });

if (!this.wsInternalSubscribed) {
(0, debug_1.Debug)('subscribing to server upgrade event');
server.on('upgrade', this.handleUpgrade);

@@ -65,6 +67,6 @@ // prevent duplicate upgrade handling;

this.handleUpgrade = async (req, socket, head) => {
if (this.shouldProxy(this.config.context, req)) {
if (this.shouldProxy(this.proxyOptions.pathFilter, req)) {
const activeProxyOptions = await this.prepareProxyRequest(req);
this.proxy.ws(req, socket, head, activeProxyOptions);
this.logger.info('[HPM] Upgrading to WebSocket');
(0, debug_1.Debug)('server upgrade event received. Proxying WebSocket');
}

@@ -74,11 +76,5 @@ };

* Determine whether request should be proxied.
*
* @private
* @param {String} context [description]
* @param {Object} req [description]
* @return {Boolean}
*/
this.shouldProxy = (context, req) => {
const path = req.originalUrl || req.url;
return contextMatcher.match(context, path, req);
this.shouldProxy = (pathFilter, req) => {
return (0, path_filter_1.matchPathFilter)(pathFilter, req.url, req);
};

@@ -94,7 +90,10 @@ /**

this.prepareProxyRequest = async (req) => {
// https://github.com/chimurai/http-proxy-middleware/issues/17
// https://github.com/chimurai/http-proxy-middleware/issues/94
req.url = req.originalUrl || req.url;
// store uri before it gets rewritten for logging
const originalPath = req.url;
/**
* Incorrect usage confirmed: https://github.com/expressjs/express/issues/4854#issuecomment-1066171160
* Temporary restore req.url patch for {@link src/legacy/create-proxy-middleware.ts legacyCreateProxyMiddleware()}
* FIXME: remove this patch in future release
*/
if (this.middleware.__LEGACY_HTTP_PROXY_MIDDLEWARE__) {
req.url = req.originalUrl || req.url;
}
const newProxyOptions = Object.assign({}, this.proxyOptions);

@@ -106,7 +105,2 @@ // Apply in order:

await this.applyPathRewrite(req, this.pathRewriter);
// debug logging for both http(s) and websockets
if (this.proxyOptions.logLevel === 'debug') {
const arrow = (0, logger_1.getArrow)(originalPath, req.url, this.proxyOptions.target, newProxyOptions.target);
this.logger.debug('[HPM] %s %s %s %s', req.method, originalPath, arrow, newProxyOptions.target);
}
return newProxyOptions;

@@ -120,3 +114,3 @@ };

if (newTarget) {
this.logger.debug('[HPM] Router new target: %s -> "%s"', options.target, newTarget);
(0, debug_1.Debug)('router new target: "%s"', newTarget);
options.target = newTarget;

@@ -131,28 +125,16 @@ }

if (typeof path === 'string') {
(0, debug_1.Debug)('pathRewrite new path: %s', req.url);
req.url = path;
}
else {
this.logger.info('[HPM] pathRewrite: No rewritten path found. (%s)', req.url);
(0, debug_1.Debug)('pathRewrite: no rewritten path found: %s', req.url);
}
}
};
this.logError = (err, req, res, target) => {
var _a;
const hostname = ((_a = req.headers) === null || _a === void 0 ? void 0 : _a.host) || req.hostname || req.host; // (websocket) || (node0.10 || node 4/5)
const requestHref = `${hostname}${req.url}`;
const targetHref = `${target === null || target === void 0 ? void 0 : target.href}`; // target is undefined when websocket errors
const errorMessage = '[HPM] Error occurred while proxying request %s to %s [%s] (%s)';
const errReference = 'https://nodejs.org/api/errors.html#errors_common_system_errors'; // link to Node Common Systems Errors page
this.logger.error(errorMessage, requestHref, targetHref, err.code || err, errReference);
};
this.config = (0, config_factory_1.createConfig)(context, opts);
this.proxyOptions = this.config.options;
// create proxy
(0, configuration_1.verifyConfig)(options);
this.proxyOptions = options;
(0, debug_1.Debug)(`create proxy server`);
this.proxy = httpProxy.createProxyServer({});
this.logger.info(`[HPM] Proxy created: ${this.config.context} -> ${this.proxyOptions.target}`);
this.registerPlugins(this.proxy, this.proxyOptions);
this.pathRewriter = PathRewriter.createPathRewriter(this.proxyOptions.pathRewrite); // returns undefined when "pathRewrite" is not provided
// attach handler to http-proxy events
handlers.init(this.proxy, this.proxyOptions);
// log errors for debug purpose
this.proxy.on('error', this.logError);
// https://github.com/chimurai/http-proxy-middleware/issues/19

@@ -166,3 +148,10 @@ // expose function to upgrade externally

}
registerPlugins(proxy, options) {
const plugins = (0, get_plugins_1.getPlugins)(options);
plugins.forEach((plugin) => {
(0, debug_1.Debug)(`register plugin: "${(0, function_1.getFunctionName)(plugin)}"`);
plugin(proxy, options);
});
}
}
exports.HttpProxyMiddleware = HttpProxyMiddleware;

@@ -1,4 +0,12 @@

import { Filter, Options } from './types';
export declare function createProxyMiddleware(context: Filter | Options, options?: Options): import("./types").RequestHandler;
import type { Options, RequestHandler } from './types';
export declare function createProxyMiddleware(options: Options): RequestHandler;
export * from './handlers';
export { Filter, Options, RequestHandler } from './types';
export type { Filter, Options, RequestHandler } from './types';
/**
* Default plugins
*/
export * from './plugins/default';
/**
* Legacy exports
*/
export * from './legacy';
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {

@@ -15,4 +19,4 @@ if (k2 === undefined) k2 = k;

const http_proxy_middleware_1 = require("./http-proxy-middleware");
function createProxyMiddleware(context, options) {
const { middleware } = new http_proxy_middleware_1.HttpProxyMiddleware(context, options);
function createProxyMiddleware(options) {
const { middleware } = new http_proxy_middleware_1.HttpProxyMiddleware(options);
return middleware;

@@ -22,1 +26,9 @@ }

__exportStar(require("./handlers"), exports);
/**
* Default plugins
*/
__exportStar(require("./plugins/default"), exports);
/**
* Legacy exports
*/
__exportStar(require("./legacy"), exports);

@@ -1,14 +0,2 @@

export declare function getInstance(): any;
/**
* -> normal proxy
* => router
* ~> pathRewrite
* ≈> router + pathRewrite
*
* @param {String} originalPath
* @param {String} newPath
* @param {String} originalTarget
* @param {String} newTarget
* @return {String}
*/
export declare function getArrow(originalPath: any, newPath: any, originalTarget: any, newTarget: any): string;
import { Logger, Options } from './types';
export declare function getLogger(options: Options): Logger;
"use strict";
/* eslint-disable prefer-rest-params */
/* eslint-disable @typescript-eslint/no-empty-function */
Object.defineProperty(exports, "__esModule", { value: true });
exports.getArrow = exports.getInstance = void 0;
const util = require("util");
let loggerInstance;
const defaultProvider = {
// tslint:disable: no-console
log: console.log,
debug: console.log,
info: console.info,
warn: console.warn,
error: console.error,
};
// log level 'weight'
var LEVELS;
(function (LEVELS) {
LEVELS[LEVELS["debug"] = 10] = "debug";
LEVELS[LEVELS["info"] = 20] = "info";
LEVELS[LEVELS["warn"] = 30] = "warn";
LEVELS[LEVELS["error"] = 50] = "error";
LEVELS[LEVELS["silent"] = 80] = "silent";
})(LEVELS || (LEVELS = {}));
function getInstance() {
if (!loggerInstance) {
loggerInstance = new Logger();
}
return loggerInstance;
}
exports.getInstance = getInstance;
class Logger {
constructor() {
this.setLevel('info');
this.setProvider(() => defaultProvider);
}
// log will log messages, regardless of logLevels
log() {
this.provider.log(this._interpolate.apply(null, arguments));
}
debug() {
if (this._showLevel('debug')) {
this.provider.debug(this._interpolate.apply(null, arguments));
}
}
info() {
if (this._showLevel('info')) {
this.provider.info(this._interpolate.apply(null, arguments));
}
}
warn() {
if (this._showLevel('warn')) {
this.provider.warn(this._interpolate.apply(null, arguments));
}
}
error() {
if (this._showLevel('error')) {
this.provider.error(this._interpolate.apply(null, arguments));
}
}
setLevel(v) {
if (this.isValidLevel(v)) {
this.logLevel = v;
}
}
setProvider(fn) {
if (fn && this.isValidProvider(fn)) {
this.provider = fn(defaultProvider);
}
}
isValidProvider(fnProvider) {
const result = true;
if (fnProvider && typeof fnProvider !== 'function') {
throw new Error('[HPM] Log provider config error. Expecting a function.');
}
return result;
}
isValidLevel(levelName) {
const validLevels = Object.keys(LEVELS);
const isValid = validLevels.includes(levelName);
if (!isValid) {
throw new Error('[HPM] Log level error. Invalid logLevel.');
}
return isValid;
}
/**
* Decide to log or not to log, based on the log levels 'weight'
* @param {String} showLevel [debug, info, warn, error, silent]
* @return {Boolean}
*/
_showLevel(showLevel) {
let result = false;
const currentLogLevel = LEVELS[this.logLevel];
if (currentLogLevel && currentLogLevel <= LEVELS[showLevel]) {
result = true;
}
return result;
}
// make sure logged messages and its data are return interpolated
// make it possible for additional log data, such date/time or custom prefix.
_interpolate(format, ...args) {
const result = util.format(format, ...args);
return result;
}
}
exports.getLogger = void 0;
/**
* -> normal proxy
* => router
* ~> pathRewrite
* ≈> router + pathRewrite
* Compatibility matrix
*
* @param {String} originalPath
* @param {String} newPath
* @param {String} originalTarget
* @param {String} newTarget
* @return {String}
| Library | log | info | warn | error | \<interpolation\> |
|----------|:------|:-------|:------|:--------|:------------------|
| console | ✅ | ✅ | ✅ | ✅ | ✅ (%s %o %O) |
| bunyan | ❌ | ✅ | ✅ | ✅ | ✅ (%s %o %O) |
| pino | ❌ | ✅ | ✅ | ✅ | ✅ (%s %o %O) |
| winston | ❌ | ✅ | ✅ | ✅ | ✅ (%s %o %O)^1 |
| log4js | ❌ | ✅ | ✅ | ✅ | ✅ (%s %o %O) |
*
* ^1: https://github.com/winstonjs/winston#string-interpolation
*/
function getArrow(originalPath, newPath, originalTarget, newTarget) {
const arrow = ['>'];
const isNewTarget = originalTarget !== newTarget; // router
const isNewPath = originalPath !== newPath; // pathRewrite
if (isNewPath && !isNewTarget) {
arrow.unshift('~');
}
else if (!isNewPath && isNewTarget) {
arrow.unshift('=');
}
else if (isNewPath && isNewTarget) {
arrow.unshift('≈');
}
else {
arrow.unshift('-');
}
return arrow.join('');
const noopLogger = {
info: () => { },
warn: () => { },
error: () => { },
};
function getLogger(options) {
return options.logger || noopLogger;
}
exports.getArrow = getArrow;
exports.getLogger = getLogger;

@@ -6,4 +6,4 @@ "use strict";

const errors_1 = require("./errors");
const logger_1 = require("./logger");
const logger = (0, logger_1.getInstance)();
const debug_1 = require("./debug");
const debug = debug_1.Debug.extend('path-rewriter');
/**

@@ -33,3 +33,3 @@ * Create rewrite function, to cache parsed rewrite rules.

result = result.replace(rule.regex, rule.value);
logger.debug('[HPM] Rewriting path from "%s" to "%s"', path, result);
debug('rewriting path from "%s" to "%s"', path, result);
break;

@@ -59,8 +59,8 @@ }

if (isPlainObj(rewriteConfig)) {
for (const [key] of Object.entries(rewriteConfig)) {
for (const [key, value] of Object.entries(rewriteConfig)) {
rules.push({
regex: new RegExp(key),
value: rewriteConfig[key],
value: value,
});
logger.info('[HPM] Proxy rewrite rule created: "%s" ~> "%s"', key, rewriteConfig[key]);
debug('rewrite rule created: "%s" ~> "%s"', key, value);
}

@@ -67,0 +67,0 @@ }

@@ -5,4 +5,4 @@ "use strict";

const isPlainObj = require("is-plain-obj");
const logger_1 = require("./logger");
const logger = (0, logger_1.getInstance)();
const debug_1 = require("./debug");
const debug = debug_1.Debug.extend('router');
async function getTarget(req, config) {

@@ -25,8 +25,8 @@ let newTarget;

const hostAndPath = host + path;
for (const [key] of Object.entries(table)) {
for (const [key, value] of Object.entries(table)) {
if (containsPath(key)) {
if (hostAndPath.indexOf(key) > -1) {
// match 'localhost:3000/api'
result = table[key];
logger.debug('[HPM] Router table match: "%s"', key);
result = value;
debug('match: "%s" -> "%s"', key, result);
break;

@@ -38,4 +38,4 @@ }

// match 'localhost:3000'
result = table[key];
logger.debug('[HPM] Router table match: "%s"', host);
result = value;
debug('match: "%s" -> "%s"', host, result);
break;

@@ -42,0 +42,0 @@ }

@@ -6,50 +6,86 @@ /**

/// <reference types="node" />
import type * as express from 'express';
import type * as http from 'http';
import type * as httpProxy from 'http-proxy';
import type * as net from 'net';
import type * as url from 'url';
export interface Request extends express.Request {
}
export interface Response extends express.Response {
}
export interface RequestHandler extends express.RequestHandler {
export declare type Request<T = http.IncomingMessage> = T;
export declare type Response<T = http.ServerResponse> = T;
export declare type NextFunction<T = (err?: any) => void> = T;
export interface RequestHandler {
(req: Request, res: Response, next?: NextFunction): void | Promise<void>;
upgrade?: (req: Request, socket: net.Socket, head: any) => void;
}
export declare type Filter = string | string[] | ((pathname: string, req: Request) => boolean);
export declare type Plugin = (proxyServer: httpProxy, options: Options) => void;
export declare type OnProxyEvent = {
error?: httpProxy.ErrorCallback;
proxyReq?: httpProxy.ProxyReqCallback;
proxyReqWs?: httpProxy.ProxyReqWsCallback;
proxyRes?: httpProxy.ProxyResCallback;
open?: httpProxy.OpenCallback;
close?: httpProxy.CloseCallback;
start?: httpProxy.StartCallback;
end?: httpProxy.EndCallback;
econnreset?: httpProxy.EconnresetCallback;
};
export declare type Logger = Pick<Console, 'info' | 'warn' | 'error'>;
export interface Options extends httpProxy.ServerOptions {
/**
* Narrow down requests to proxy or not.
* Filter on {@link http.IncomingMessage.url `pathname`} which is relative to the proxy's "mounting" point in the server.
* Or use the {@link http.IncomingMessage `req`} object for more complex filtering.
*/
pathFilter?: Filter;
pathRewrite?: {
[regexp: string]: string;
} | ((path: string, req: Request) => string) | ((path: string, req: Request) => Promise<string>);
/**
* Access the internal http-proxy server instance to customize behavior
*
* @example
* ```js
* createProxyMiddleware({
* plugins: [(proxyServer, options) => {
* proxyServer.on('error', (error, req, res) => {
* console.error(error);
* });
* }]
* });
* ```
*/
plugins?: Plugin[];
/**
* Eject pre-configured plugins.
* NOTE: register your own error handlers to prevent server from crashing.
*
* @since v3.0.0
*/
ejectPlugins?: boolean;
/**
* Listen to http-proxy events
* @see {@link OnProxyEvent} for available events
* @example
* ```js
* createProxyMiddleware({
* on: {
* error: (error, req, res, target) => {
* console.error(error);
* }
* }
* });
* ```
*/
on?: OnProxyEvent;
router?: {
[hostOrPath: string]: httpProxy.ServerOptions['target'];
} | ((req: Request) => httpProxy.ServerOptions['target']) | ((req: Request) => Promise<httpProxy.ServerOptions['target']>);
logLevel?: 'debug' | 'info' | 'warn' | 'error' | 'silent';
logProvider?: LogProviderCallback;
onError?: OnErrorCallback;
onProxyRes?: OnProxyResCallback;
onProxyReq?: OnProxyReqCallback;
onProxyReqWs?: OnProxyReqWsCallback;
onOpen?: OnOpenCallback;
onClose?: OnCloseCallback;
/**
* Log information from http-proxy-middleware
* @example
* ```js
* createProxyMiddleware({
* logger: console
* });
* ```
*/
logger?: Logger | any;
}
interface LogProvider {
log: Logger;
debug?: Logger;
info?: Logger;
warn?: Logger;
error?: Logger;
}
declare type Logger = (...args: any[]) => void;
export declare type LogProviderCallback = (provider: LogProvider) => LogProvider;
/**
* Use types based on the events listeners from http-proxy
* https://github.com/DefinitelyTyped/DefinitelyTyped/blob/51504fd999031b7f025220fab279f1b2155cbaff/types/http-proxy/index.d.ts
*/
export declare type OnErrorCallback = (err: Error, req: Request, res: Response, target?: string | Partial<url.Url>) => void;
export declare type OnProxyResCallback = (proxyRes: http.IncomingMessage, req: Request, res: Response) => void;
export declare type OnProxyReqCallback = (proxyReq: http.ClientRequest, req: Request, res: Response, options: httpProxy.ServerOptions) => void;
export declare type OnProxyReqWsCallback = (proxyReq: http.ClientRequest, req: Request, socket: net.Socket, options: httpProxy.ServerOptions, head: any) => void;
export declare type OnCloseCallback = (proxyRes: Response, proxySocket: net.Socket, proxyHead: any) => void;
export declare type OnOpenCallback = (proxySocket: net.Socket) => void;
export {};
{
"name": "http-proxy-middleware",
"version": "2.0.6",
"description": "The one-liner node.js proxy middleware for connect, express and browser-sync",
"version": "3.0.0-beta.0",
"description": "The one-liner node.js proxy middleware for connect, express, next.js and more",
"main": "dist/index.js",

@@ -42,2 +42,3 @@ "types": "dist/index.d.ts",

"polka",
"next.js",
"browser-sync",

@@ -57,18 +58,19 @@ "gulp",

"devDependencies": {
"@commitlint/cli": "16.2.1",
"@commitlint/cli": "16.2.3",
"@commitlint/config-conventional": "16.2.1",
"@types/debug": "4.1.7",
"@types/express": "4.17.13",
"@types/is-glob": "4.0.2",
"@types/jest": "27.4.0",
"@types/jest": "27.4.1",
"@types/micromatch": "4.0.2",
"@types/node": "17.0.18",
"@types/supertest": "2.0.11",
"@types/ws": "8.2.2",
"@typescript-eslint/eslint-plugin": "5.12.0",
"@typescript-eslint/parser": "5.12.0",
"body-parser": "1.19.2",
"browser-sync": "2.27.7",
"@types/node": "17.0.25",
"@types/supertest": "2.0.12",
"@types/ws": "8.5.3",
"@typescript-eslint/eslint-plugin": "5.20.0",
"@typescript-eslint/parser": "5.20.0",
"body-parser": "1.20.0",
"browser-sync": "2.27.9",
"connect": "3.7.0",
"eslint": "8.9.0",
"eslint-config-prettier": "8.3.0",
"eslint": "8.13.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-prettier": "4.0.0",

@@ -79,9 +81,9 @@ "express": "4.17.3",

"jest": "27.5.1",
"lint-staged": "12.3.4",
"mockttp": "2.6.0",
"lint-staged": "12.3.8",
"mockttp": "2.7.0",
"open": "8.4.0",
"prettier": "2.5.1",
"prettier": "2.6.2",
"supertest": "6.2.2",
"ts-jest": "27.1.3",
"typescript": "4.5.5",
"ts-jest": "27.1.4",
"typescript": "4.6.3",
"ws": "8.5.0"

@@ -91,6 +93,7 @@ },

"@types/http-proxy": "^1.17.8",
"debug": "^4.3.4",
"http-proxy": "^1.18.1",
"is-glob": "^4.0.1",
"is-plain-obj": "^3.0.0",
"micromatch": "^4.0.2"
"micromatch": "^4.0.5"
},

@@ -105,2 +108,5 @@ "peerDependencies": {

},
"resolutions": {
"browser-sync/portscanner": "2.2.0"
},
"engines": {

@@ -107,0 +113,0 @@ "node": ">=12.0.0"

@@ -8,3 +8,3 @@ # http-proxy-middleware

Node.js proxying made simple. Configure proxy middleware with ease for [connect](https://github.com/senchalabs/connect), [express](https://github.com/strongloop/express), [browser-sync](https://github.com/BrowserSync/browser-sync) and [many more](#compatible-servers).
Node.js proxying made simple. Configure proxy middleware with ease for [connect](https://github.com/senchalabs/connect), [express](https://github.com/expressjs/express), [next.js](https://github.com/vercel/next.js) and [many more](#compatible-servers).

@@ -15,7 +15,11 @@ Powered by the popular Nodejitsu [`http-proxy`](https://github.com/nodejitsu/node-http-proxy). [![GitHub stars](https://img.shields.io/github/stars/nodejitsu/node-http-proxy.svg?style=social&label=Star)](https://github.com/nodejitsu/node-http-proxy)

This page is showing documentation for version v2.x.x ([release notes](https://github.com/chimurai/http-proxy-middleware/releases))
This page is showing documentation for version v3.x.x ([release notes](https://github.com/chimurai/http-proxy-middleware/releases))
If you're looking for v0.x documentation. Go to:
https://github.com/chimurai/http-proxy-middleware/tree/v0.21.0#readme
See [MIGRATION.md](https://github.com/chimurai/http-proxy-middleware/blob/master/MIGRATION.md) for details on how to migrate from v2.x.x to v3.x.x
If you're looking for older documentation. Go to:
- <https://github.com/chimurai/http-proxy-middleware/tree/v2.0.4#readme>
- <https://github.com/chimurai/http-proxy-middleware/tree/v0.21.0#readme>
## TL;DR <!-- omit in toc -->

@@ -25,2 +29,4 @@

:bulb: **Tip:** Set the option `changeOrigin` to `true` for [name-based virtual hosted sites](http://en.wikipedia.org/wiki/Virtual_hosting#Name-based).
```javascript

@@ -34,6 +40,14 @@ // javascript

app.use('/api', createProxyMiddleware({ target: 'http://www.example.org', changeOrigin: true }));
app.use(
'/api',
createProxyMiddleware({
target: 'http://www.example.org/secret',
changeOrigin: true,
})
);
app.listen(3000);
// http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar
// proxy and change the base path from "/api" to "/secret"
// http://localhost:3000/api/foo/bar -> http://www.example.org/secret/foo/bar
```

@@ -49,5 +63,13 @@

app.use('/api', createProxyMiddleware({ target: 'http://www.example.org', changeOrigin: true }));
app.use(
'/api',
createProxyMiddleware({
target: 'http://www.example.org/api',
changeOrigin: true,
})
);
app.listen(3000);
// proxy and keep the same base path "/api"
// http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar

@@ -58,16 +80,19 @@ ```

:bulb: **Tip:** Set the option `changeOrigin` to `true` for [name-based virtual hosted sites](http://en.wikipedia.org/wiki/Virtual_hosting#Name-based).
## Table of Contents <!-- omit in toc -->
<!-- // spell-checker:disable -->
- [Install](#install)
- [Core concept](#core-concept)
- [Example](#example)
- [Context matching](#context-matching)
- [Basic usage](#basic-usage)
- [Express Server Example](#express-server-example)
- [app.use(path, proxy)](#appusepath-proxy)
- [Options](#options)
- [http-proxy-middleware options](#http-proxy-middleware-options)
- [http-proxy events](#http-proxy-events)
- [http-proxy options](#http-proxy-options)
- [Shorthand](#shorthand)
- [app.use(path, proxy)](#appusepath-proxy)
- [`pathFilter` (string, []string, glob, []glob, function)](#pathfilter-string-string-glob-glob-function)
- [`pathRewrite` (object/function)](#pathrewrite-objectfunction)
- [`router` (object/function)](#router-objectfunction)
- [`plugins` (Array)](#plugins-array)
- [`ejectPlugins` (boolean) default: `false`](#ejectplugins-boolean-default-false)
- [`logger` (Object)](#logger-object)
- [`http-proxy` events](#http-proxy-events)
- [`http-proxy` options](#http-proxy-options)
- [WebSocket](#websocket)

@@ -77,2 +102,3 @@ - [External WebSocket upgrade](#external-websocket-upgrade)

- [Intercept and manipulate responses](#intercept-and-manipulate-responses)
- [Debugging](#debugging)
- [Working examples](#working-examples)

@@ -85,21 +111,21 @@ - [Recipes](#recipes)

<!-- // spell-checker:enable -->
## Install
```bash
$ npm install --save-dev http-proxy-middleware
```shell
npm install --save-dev http-proxy-middleware
```
## Core concept
## Basic usage
Proxy middleware configuration.
Create and configure a proxy middleware with: `createProxyMiddleware(config)`.
#### createProxyMiddleware([context,] config)
```javascript
const { createProxyMiddleware } = require('http-proxy-middleware');
const apiProxy = createProxyMiddleware('/api', { target: 'http://www.example.org' });
// \____/ \_____________________________/
// | |
// context options
const apiProxy = createProxyMiddleware({
target: 'http://www.example.org',
changeOrigin: true,
});

@@ -109,19 +135,9 @@ // 'apiProxy' is now ready to be used as middleware in a server.

- **context**: Determine which requests should be proxied to the target host.
(more on [context matching](#context-matching))
- **options.target**: target host to proxy to. _(protocol + host)_
- **options.changeOrigin**: for virtual hosted sites
(full list of [`http-proxy-middleware` configuration options](#options))
- see full list of [`http-proxy-middleware` configuration options](#options)
#### createProxyMiddleware(uri [, config])
## Express Server Example
```javascript
// shorthand syntax for the example above:
const apiProxy = createProxyMiddleware('http://www.example.org/api');
```
More about the [shorthand configuration](#shorthand).
## Example
An example with `express` server.

@@ -134,24 +150,15 @@

const app = express();
// proxy middleware options
/** @type {import('http-proxy-middleware/dist/types').Options} */
const options = {
target: 'http://www.example.org', // target host
target: 'http://www.example.org/api', // target host with the same base path
changeOrigin: true, // needed for virtual hosted sites
ws: true, // proxy websockets
pathRewrite: {
'^/api/old-path': '/api/new-path', // rewrite path
'^/api/remove/path': '/path', // remove base path
},
router: {
// when request.headers.host == 'dev.localhost:3000',
// override target 'http://www.example.org' to 'http://localhost:8000'
'dev.localhost:3000': 'http://localhost:8000',
},
};
// create the proxy (without context)
// create the proxy
const exampleProxy = createProxyMiddleware(options);
// mount `exampleProxy` in web server
const app = express();
app.use('/api', exampleProxy);

@@ -161,24 +168,39 @@ app.listen(3000);

## Context matching
### app.use(path, proxy)
Providing an alternative way to decide which requests should be proxied; In case you are not able to use the server's [`path` parameter](http://expressjs.com/en/4x/api.html#app.use) to mount the proxy or when you need more flexibility.
If you want to use the server's `app.use` `path` parameter to match requests.
Use `pathFilter` option to further include/exclude requests which you want to proxy.
[RFC 3986 `path`](https://tools.ietf.org/html/rfc3986#section-3.3) is used for context matching.
```ascii
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
```javascript
app.use(
createProxyMiddleware({
target: 'http://www.example.org/api',
changeOrigin: true,
pathFilter: '/api/proxy-only-this-path',
})
);
```
`app.use` documentation:
- express: <http://expressjs.com/en/4x/api.html#app.use>
- connect: <https://github.com/senchalabs/connect#mount-middleware>
- polka: <https://github.com/lukeed/polka#usebase-fn>
## Options
http-proxy-middleware options:
### `pathFilter` (string, []string, glob, []glob, function)
Narrow down which requests should be proxied. The `path` used for filtering is the `request.url` pathname. In Express, this is the `path` relative to the mount-point of the proxy.
- **path matching**
- `createProxyMiddleware({...})` - matches any path, all requests will be proxied.
- `createProxyMiddleware('/', {...})` - matches any path, all requests will be proxied.
- `createProxyMiddleware('/api', {...})` - matches paths starting with `/api`
- `createProxyMiddleware({...})` - matches any path, all requests will be proxied when `pathFilter` is not configured.
- `createProxyMiddleware({ pathFilter: '/api', ...})` - matches paths starting with `/api`
- **multiple path matching**
- `createProxyMiddleware(['/api', '/ajax', '/someotherpath'], {...})`
- `createProxyMiddleware({ pathFilter: ['/api', '/ajax', '/someotherpath'], ...})`

@@ -189,8 +211,8 @@ - **wildcard path matching**

- `createProxyMiddleware('**', {...})` matches any path, all requests will be proxied.
- `createProxyMiddleware('**/*.html', {...})` matches any path which ends with `.html`
- `createProxyMiddleware('/*.html', {...})` matches paths directly under path-absolute
- `createProxyMiddleware('/api/**/*.html', {...})` matches requests ending with `.html` in the path of `/api`
- `createProxyMiddleware(['/api/**', '/ajax/**'], {...})` combine multiple patterns
- `createProxyMiddleware(['/api/**', '!**/bad.json'], {...})` exclusion
- `createProxyMiddleware({ pathFilter: '**', ...})` matches any path, all requests will be proxied.
- `createProxyMiddleware({ pathFilter: '**/*.html', ...})` matches any path which ends with `.html`
- `createProxyMiddleware({ pathFilter: '/*.html', ...})` matches paths directly under path-absolute
- `createProxyMiddleware({ pathFilter: '/api/**/*.html', ...})` matches requests ending with `.html` in the path of `/api`
- `createProxyMiddleware({ pathFilter: ['/api/**', '/ajax/**'], ...})` combine multiple patterns
- `createProxyMiddleware({ pathFilter: ['/api/**', '!**/bad.json'], ...})` exclusion

@@ -207,105 +229,151 @@ **Note**: In multiple path matching, you cannot use string paths and wildcard paths together.

*/
const filter = function (pathname, req) {
return pathname.match('^/api') && req.method === 'GET';
const pathFilter = function (path, req) {
return path.match('^/api') && req.method === 'GET';
};
const apiProxy = createProxyMiddleware(filter, {
const apiProxy = createProxyMiddleware({
target: 'http://www.example.org',
pathFilter: pathFilter,
});
```
## Options
### `pathRewrite` (object/function)
### http-proxy-middleware options
Rewrite target's url path. Object-keys will be used as _RegExp_ to match paths.
- **option.pathRewrite**: object/function, rewrite target's url path. Object-keys will be used as _RegExp_ to match paths.
```javascript
// rewrite path
pathRewrite: {'^/old/api' : '/new/api'}
```javascript
// rewrite path
pathRewrite: {'^/old/api' : '/new/api'}
// remove path
pathRewrite: {'^/remove/api' : ''}
// remove path
pathRewrite: {'^/remove/api' : ''}
// add base path
pathRewrite: {'^/' : '/basepath/'}
// add base path
pathRewrite: {'^/' : '/basepath/'}
// custom rewriting
pathRewrite: function (path, req) { return path.replace('/api', '/base/api') }
// custom rewriting
pathRewrite: function (path, req) { return path.replace('/api', '/base/api') }
// custom rewriting, returning Promise
pathRewrite: async function (path, req) {
const should_add_something = await httpRequestToDecideSomething(path);
if (should_add_something) path += "something";
return path;
}
```
// custom rewriting, returning Promise
pathRewrite: async function (path, req) {
const should_add_something = await httpRequestToDecideSomething(path);
if (should_add_something) path += "something";
return path;
}
```
### `router` (object/function)
- **option.router**: object/function, re-target `option.target` for specific requests.
Re-target `option.target` for specific requests.
```javascript
// Use `host` and/or `path` to match requests. First match will be used.
// The order of the configuration matters.
router: {
'integration.localhost:3000' : 'http://localhost:8001', // host only
'staging.localhost:3000' : 'http://localhost:8002', // host only
'localhost:3000/api' : 'http://localhost:8003', // host + path
'/rest' : 'http://localhost:8004' // path only
}
```javascript
// Use `host` and/or `path` to match requests. First match will be used.
// The order of the configuration matters.
router: {
'integration.localhost:3000' : 'http://localhost:8001', // host only
'staging.localhost:3000' : 'http://localhost:8002', // host only
'localhost:3000/api' : 'http://localhost:8003', // host + path
'/rest' : 'http://localhost:8004' // path only
}
// Custom router function (string target)
router: function(req) {
return 'http://localhost:8004';
}
// Custom router function (string target)
router: function(req) {
return 'http://localhost:8004';
}
// Custom router function (target object)
router: function(req) {
return {
protocol: 'https:', // The : is required
host: 'localhost',
port: 8004
};
}
// Custom router function (target object)
router: function(req) {
return {
protocol: 'https:', // The : is required
host: 'localhost',
port: 8004
};
}
// Asynchronous router function which returns promise
router: async function(req) {
const url = await doSomeIO();
return url;
}
```
// Asynchronous router function which returns promise
router: async function(req) {
const url = await doSomeIO();
return url;
}
```
- **option.logLevel**: string, ['debug', 'info', 'warn', 'error', 'silent']. Default: `'info'`
### `plugins` (Array)
- **option.logProvider**: function, modify or replace log provider. Default: `console`.
```js
const simpleRequestLogger = (proxyServer, options) => {
proxyServer.on('proxyReq', (proxyReq, req, res) => {
console.log(`[HPM] [${req.method}] ${req.url}`); // outputs: [HPM] GET /users
});
},
```javascript
// simple replace
function logProvider(provider) {
// replace the default console log provider.
return require('winston');
}
```
const config = {
target: `http://example.org`,
changeOrigin: true,
plugins: [simpleRequestLogger],
};
```
```javascript
// verbose replacement
function logProvider(provider) {
const logger = new (require('winston').Logger)();
### `ejectPlugins` (boolean) default: `false`
const myCustomProvider = {
log: logger.log,
debug: logger.debug,
info: logger.info,
warn: logger.warn,
error: logger.error,
};
return myCustomProvider;
}
```
If you're not satisfied with the pre-configured plugins, you can eject them by configuring `ejectPlugins: true`.
### http-proxy events
NOTE: register your own error handlers to prevent server from crashing.
Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#listening-for-proxy-events):
```js
// eject default plugins and manually add them back
- **option.onError**: function, subscribe to http-proxy's `error` event for custom error handling.
const {
debugProxyErrorsPlugin, // subscribe to proxy errors to prevent server from crashing
loggerPlugin, // log proxy events to a logger (ie. console)
errorResponsePlugin, // return 5xx response on proxy error
proxyEventsPlugin, // implements the "on:" option
} = require('http-proxy-middleware');
createProxyMiddleware({
target: `http://example.org`,
changeOrigin: true,
ejectPlugins: true,
plugins: [debugProxyErrorsPlugin, loggerPlugin, errorResponsePlugin, proxyEventsPlugin],
});
```
### `logger` (Object)
Configure a logger to output information from http-proxy-middleware: ie. `console`, `winston`, `pino`, `bunyan`, `log4js`, etc...
Only `info`, `warn`, `error` are used internally for compatibility across different loggers.
If you use `winston`, make sure to enable interpolation: <https://github.com/winstonjs/winston#string-interpolation>
See also logger recipes ([recipes/logger.md](https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/logger.md)) for more details.
```javascript
createProxyMiddleware({
logger: console,
});
```
## `http-proxy` events
Subscribe to [http-proxy events](https://github.com/nodejitsu/node-http-proxy#listening-for-proxy-events) with the `on` option:
```js
createProxyMiddleware({
target: 'http://www.example.org',
on: {
proxyReq: (proxyReq, req, res) => {
/* handle proxyReq */
},
proxyRes: (proxyRes, req, res) => {
/* handle proxyRes */
},
error: (err, req, res) => {
/* handle error */
},
},
});
```
- **option.on.error**: function, subscribe to http-proxy's `error` event for custom error handling.
```javascript

@@ -320,3 +388,3 @@ function onError(err, req, res, target) {

- **option.onProxyRes**: function, subscribe to http-proxy's `proxyRes` event.
- **option.on.proxyRes**: function, subscribe to http-proxy's `proxyRes` event.

@@ -330,3 +398,3 @@ ```javascript

- **option.onProxyReq**: function, subscribe to http-proxy's `proxyReq` event.
- **option.on.proxyReq**: function, subscribe to http-proxy's `proxyReq` event.

@@ -341,3 +409,3 @@ ```javascript

- **option.onProxyReqWs**: function, subscribe to http-proxy's `proxyReqWs` event.
- **option.on.proxyReqWs**: function, subscribe to http-proxy's `proxyReqWs` event.

@@ -351,3 +419,3 @@ ```javascript

- **option.onOpen**: function, subscribe to http-proxy's `open` event.
- **option.on.open**: function, subscribe to http-proxy's `open` event.

@@ -361,3 +429,3 @@ ```javascript

- **option.onClose**: function, subscribe to http-proxy's `close` event.
- **option.on.close**: function, subscribe to http-proxy's `close` event.

@@ -371,3 +439,3 @@ ```javascript

### http-proxy options
## `http-proxy` options

@@ -394,2 +462,3 @@ The following options are provided by the underlying [http-proxy](https://github.com/nodejitsu/node-http-proxy#options) library.

- **option.cookieDomainRewrite**: rewrites domain of `set-cookie` headers. Possible values:
- `false` (default): disable cookie rewriting

@@ -399,2 +468,3 @@ - String: new domain, for example `cookieDomainRewrite: "new.domain"`. To remove the domain, use `cookieDomainRewrite: ""`.

For example keep one domain unchanged, rewrite one domain and remove other domains:
```json

@@ -407,3 +477,5 @@ cookieDomainRewrite: {

```
- **option.cookiePathRewrite**: rewrites path of `set-cookie` headers. Possible values:
- `false` (default): disable cookie rewriting

@@ -413,2 +485,3 @@ - String: new path, for example `cookiePathRewrite: "/newPath/"`. To remove the path, use `cookiePathRewrite: ""`. To set path to root use `cookiePathRewrite: "/"`.

For example, to keep one path unchanged, rewrite one path and remove other paths:
```json

@@ -421,2 +494,3 @@ cookiePathRewrite: {

```
- **option.headers**: object, adds [request headers](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields). (Example: `{host:'www.example.org'}`)

@@ -449,32 +523,2 @@ - **option.proxyTimeout**: timeout (in millis) when proxy receives no response from target

## Shorthand
Use the shorthand syntax when verbose configuration is not needed. The `context` and `option.target` will be automatically configured when shorthand is used. Options can still be used if needed.
```javascript
createProxyMiddleware('http://www.example.org:8000/api');
// createProxyMiddleware('/api', {target: 'http://www.example.org:8000'});
createProxyMiddleware('http://www.example.org:8000/api/books/*/**.json');
// createProxyMiddleware('/api/books/*/**.json', {target: 'http://www.example.org:8000'});
createProxyMiddleware('http://www.example.org:8000/api', { changeOrigin: true });
// createProxyMiddleware('/api', {target: 'http://www.example.org:8000', changeOrigin: true});
```
### app.use(path, proxy)
If you want to use the server's `app.use` `path` parameter to match requests;
Create and mount the proxy without the http-proxy-middleware `context` parameter:
```javascript
app.use('/api', createProxyMiddleware({ target: 'http://www.example.org', changeOrigin: true }));
```
`app.use` documentation:
- express: http://expressjs.com/en/4x/api.html#app.use
- connect: https://github.com/senchalabs/connect#mount-middleware
- polka: https://github.com/lukeed/polka#usebase-fn
## WebSocket

@@ -484,9 +528,3 @@

// verbose api
createProxyMiddleware('/', { target: 'http://echo.websocket.org', ws: true });
// shorthand
createProxyMiddleware('http://echo.websocket.org', { ws: true });
// shorter shorthand
createProxyMiddleware('ws://echo.websocket.org');
createProxyMiddleware({ pathFilter: '/', target: 'http://echo.websocket.org', ws: true });
```

@@ -499,3 +537,3 @@

```javascript
const wsProxy = createProxyMiddleware('ws://echo.websocket.org', { changeOrigin: true });
const wsProxy = createProxyMiddleware({ target: 'ws://echo.websocket.org', changeOrigin: true });

@@ -524,3 +562,5 @@ const app = express();

**/
onProxyReq: fixRequestBody,
on: {
proxyReq: fixRequestBody,
},
});

@@ -553,6 +593,8 @@ ```

**/
onProxyRes: responseInterceptor(async (responseBuffer, proxyRes, req, res) => {
const response = responseBuffer.toString('utf8'); // convert buffer to string
return response.replace('Hello', 'Goodbye'); // manipulate response and return the result
}),
on: {
proxyRes: responseInterceptor(async (responseBuffer, proxyRes, req, res) => {
const response = responseBuffer.toString('utf8'); // convert buffer to string
return response.replace('Hello', 'Goodbye'); // manipulate response and return the result
}),
},
});

@@ -563,2 +605,15 @@ ```

## Debugging
Configure the `DEBUG` environment variable enable debug logging.
See [`debug`](https://github.com/debug-js/debug#readme) project for more options.
```shell
DEBUG=http-proxy-middleware* node server.js
$ http-proxy-middleware proxy created +0ms
$ http-proxy-middleware proxying request to target: 'http://www.example.org' +359ms
```
## Working examples

@@ -584,2 +639,3 @@

- [express](https://www.npmjs.com/package/express)
- [next.js](https://www.npmjs.com/package/next)
- [fastify](https://www.npmjs.com/package/fastify)

@@ -586,0 +642,0 @@ - [browser-sync](https://www.npmjs.com/package/browser-sync)

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc