完成中转仓管理

This commit is contained in:
xuqiuyun
2025-12-08 15:24:43 +08:00
parent e968fcf52a
commit 620975c04d
981 changed files with 154245 additions and 83 deletions

View File

@@ -0,0 +1,2 @@
import { Options } from './types';
export declare function verifyConfig<TReq, TRes>(options: Options<TReq, TRes>): void;

View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.verifyConfig = verifyConfig;
const errors_1 = require("./errors");
function verifyConfig(options) {
if (!options.target && !options.router) {
throw new Error(errors_1.ERRORS.ERR_CONFIG_FACTORY_TARGET_MISSING);
}
}

View File

@@ -0,0 +1,5 @@
import * as createDebug from 'debug';
/**
* Debug instance with the given namespace: http-proxy-middleware
*/
export declare const Debug: createDebug.Debugger;

View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Debug = void 0;
const createDebug = require("debug");
/**
* Debug instance with the given namespace: http-proxy-middleware
*/
exports.Debug = createDebug('http-proxy-middleware');

View File

@@ -0,0 +1,6 @@
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 pathFilter. Expecting something like: \"/api\" or [\"/api\", \"/ajax\"]",
ERR_CONTEXT_MATCHER_INVALID_ARRAY = "[HPM] Invalid pathFilter. Plain paths (e.g. \"/api\") can not be mixed with globs (e.g. \"/api/**\"). 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"
}

View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ERRORS = void 0;
var ERRORS;
(function (ERRORS) {
ERRORS["ERR_CONFIG_FACTORY_TARGET_MISSING"] = "[HPM] Missing \"target\" option. Example: {target: \"http://www.example.org\"}";
ERRORS["ERR_CONTEXT_MATCHER_GENERIC"] = "[HPM] Invalid pathFilter. Expecting something like: \"/api\" or [\"/api\", \"/ajax\"]";
ERRORS["ERR_CONTEXT_MATCHER_INVALID_ARRAY"] = "[HPM] Invalid pathFilter. Plain paths (e.g. \"/api\") can not be mixed with globs (e.g. \"/api/**\"). 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 = ERRORS = {}));

View File

@@ -0,0 +1,3 @@
import type { Options, RequestHandler, NextFunction } from './types';
import type * as http from 'http';
export declare function createProxyMiddleware<TReq = http.IncomingMessage, TRes = http.ServerResponse, TNext = NextFunction>(options: Options<TReq, TRes>): RequestHandler<TReq, TRes, TNext>;

View File

@@ -0,0 +1,8 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createProxyMiddleware = createProxyMiddleware;
const http_proxy_middleware_1 = require("./http-proxy-middleware");
function createProxyMiddleware(options) {
const { middleware } = new http_proxy_middleware_1.HttpProxyMiddleware(options);
return middleware;
}

View File

@@ -0,0 +1,2 @@
import type { Options, Plugin } from './types';
export declare function getPlugins<TReq, TRes>(options: Options<TReq, TRes>): Plugin<TReq, TRes>[];

View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPlugins = getPlugins;
const default_1 = require("./plugins/default");
function getPlugins(options) {
// don't load default errorResponsePlugin if user has specified their own
const maybeErrorResponsePlugin = options.on?.error ? [] : [default_1.errorResponsePlugin];
const defaultPlugins = options.ejectPlugins
? [] // no default plugins when ejecting
: [default_1.debugProxyErrorsPlugin, default_1.proxyEventsPlugin, default_1.loggerPlugin, ...maybeErrorResponsePlugin];
const userPlugins = options.plugins ?? [];
return [...defaultPlugins, ...userPlugins];
}

View File

@@ -0,0 +1,8 @@
import type * as http from 'http';
export type BodyParserLikeRequest = http.IncomingMessage & {
body?: any;
};
/**
* Fix proxied body if bodyParser is involved.
*/
export declare function fixRequestBody<TReq extends BodyParserLikeRequest = BodyParserLikeRequest>(proxyReq: http.ClientRequest, req: TReq): void;

View File

@@ -0,0 +1,50 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.fixRequestBody = fixRequestBody;
const querystring = require("querystring");
/**
* Fix proxied body if bodyParser is involved.
*/
function fixRequestBody(proxyReq, req) {
// skip fixRequestBody() when req.readableLength not 0 (bodyParser failure)
if (req.readableLength !== 0) {
return;
}
const requestBody = req.body;
if (!requestBody) {
return;
}
const contentType = proxyReq.getHeader('Content-Type');
if (!contentType) {
return;
}
const writeBody = (bodyData) => {
proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
proxyReq.write(bodyData);
};
// Use if-elseif to prevent multiple writeBody/setHeader calls:
// Error: "Cannot set headers after they are sent to the client"
if (contentType.includes('application/json') || contentType.includes('+json')) {
writeBody(JSON.stringify(requestBody));
}
else if (contentType.includes('application/x-www-form-urlencoded')) {
writeBody(querystring.stringify(requestBody));
}
else if (contentType.includes('multipart/form-data')) {
writeBody(handlerFormDataBodyData(contentType, requestBody));
}
}
/**
* format FormData data
* @param contentType
* @param data
* @returns
*/
function handlerFormDataBodyData(contentType, data) {
const boundary = contentType.replace(/^.*boundary=(.*)$/, '$1');
let str = '';
for (const [key, value] of Object.entries(data)) {
str += `--${boundary}\r\nContent-Disposition: form-data; name="${key}"\r\n\r\n${value}\r\n`;
}
return str;
}

View File

@@ -0,0 +1 @@
export * from './public';

View File

@@ -0,0 +1,17 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = 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) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./public"), exports);

View File

@@ -0,0 +1,2 @@
export { responseInterceptor } from './response-interceptor';
export { fixRequestBody } from './fix-request-body';

View File

@@ -0,0 +1,7 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.fixRequestBody = exports.responseInterceptor = void 0;
var response_interceptor_1 = require("./response-interceptor");
Object.defineProperty(exports, "responseInterceptor", { enumerable: true, get: function () { return response_interceptor_1.responseInterceptor; } });
var fix_request_body_1 = require("./fix-request-body");
Object.defineProperty(exports, "fixRequestBody", { enumerable: true, get: function () { return fix_request_body_1.fixRequestBody; } });

View File

@@ -0,0 +1,11 @@
import type * as http from 'http';
type Interceptor<TReq = http.IncomingMessage, TRes = http.ServerResponse> = (buffer: Buffer, proxyRes: TReq, req: TReq, res: TRes) => Promise<Buffer | string>;
/**
* Intercept responses from upstream.
* Automatically decompress (deflate, gzip, brotli).
* Give developer the opportunity to modify intercepted Buffer and http.ServerResponse
*
* NOTE: must set options.selfHandleResponse=true (prevent automatic call of res.end())
*/
export declare function responseInterceptor<TReq extends http.IncomingMessage = http.IncomingMessage, TRes extends http.ServerResponse = http.ServerResponse>(interceptor: Interceptor<TReq, TRes>): (proxyRes: TReq, req: TReq, res: TRes) => Promise<void>;
export {};

View File

@@ -0,0 +1,94 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.responseInterceptor = responseInterceptor;
const zlib = require("zlib");
const debug_1 = require("../debug");
const function_1 = require("../utils/function");
const debug = debug_1.Debug.extend('response-interceptor');
/**
* Intercept responses from upstream.
* Automatically decompress (deflate, gzip, brotli).
* Give developer the opportunity to modify intercepted Buffer and http.ServerResponse
*
* NOTE: must set options.selfHandleResponse=true (prevent automatic call of res.end())
*/
function responseInterceptor(interceptor) {
return async function proxyResResponseInterceptor(proxyRes, req, res) {
debug('intercept proxy response');
const originalProxyRes = proxyRes;
let buffer = Buffer.from('', 'utf8');
// decompress proxy response
const _proxyRes = decompress(proxyRes, proxyRes.headers['content-encoding']);
// concat data stream
_proxyRes.on('data', (chunk) => (buffer = Buffer.concat([buffer, chunk])));
_proxyRes.on('end', async () => {
// copy original headers
copyHeaders(proxyRes, res);
// 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);
res.end();
});
_proxyRes.on('error', (error) => {
res.end(`Error fetching proxied request: ${error.message}`);
});
};
}
/**
* Streaming decompression of proxy response
* source: https://github.com/apache/superset/blob/9773aba522e957ed9423045ca153219638a85d2f/superset-frontend/webpack.proxy-config.js#L116
*/
function decompress(proxyRes, contentEncoding) {
let _proxyRes = proxyRes;
let decompress;
switch (contentEncoding) {
case 'gzip':
decompress = zlib.createGunzip();
break;
case 'br':
decompress = zlib.createBrotliDecompress();
break;
case 'deflate':
decompress = zlib.createInflate();
break;
default:
break;
}
if (decompress) {
debug(`decompress proxy response with 'content-encoding': %s`, contentEncoding);
_proxyRes.pipe(decompress);
_proxyRes = decompress;
}
return _proxyRes;
}
/**
* Copy original headers
* https://github.com/apache/superset/blob/9773aba522e957ed9423045ca153219638a85d2f/superset-frontend/webpack.proxy-config.js#L78
*/
function copyHeaders(originalResponse, response) {
debug('copy original response headers');
response.statusCode = originalResponse.statusCode;
response.statusMessage = originalResponse.statusMessage;
if (response.setHeader) {
let keys = Object.keys(originalResponse.headers);
// ignore chunked, brotli, gzip, deflate headers
keys = keys.filter((key) => !['content-encoding', 'transfer-encoding'].includes(key));
keys.forEach((key) => {
let value = originalResponse.headers[key];
if (key === 'set-cookie') {
// remove cookie domain
value = Array.isArray(value) ? value : [value];
value = value.map((x) => x.replace(/Domain=[^;]+?/i, ''));
}
response.setHeader(key, value);
});
}
else {
response.headers = originalResponse.headers;
}
}

View File

@@ -0,0 +1,29 @@
import type { RequestHandler, Options } from './types';
export declare class HttpProxyMiddleware<TReq, TRes> {
private wsInternalSubscribed;
private serverOnCloseSubscribed;
private proxyOptions;
private proxy;
private pathRewriter;
private logger;
constructor(options: Options<TReq, TRes>);
middleware: RequestHandler;
private registerPlugins;
private catchUpgradeRequest;
private handleUpgrade;
/**
* Determine whether request should be proxied.
*/
private shouldProxy;
/**
* Apply option.router and option.pathRewrite
* Order matters:
* Router uses original path for routing;
* NOT the modified path, after it has been rewritten by pathRewrite
* @param {Object} req
* @return {Object} proxy options
*/
private prepareProxyRequest;
private applyRouter;
private applyPathRewrite;
}

View File

@@ -0,0 +1,161 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HttpProxyMiddleware = void 0;
const httpProxy = require("http-proxy");
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");
const logger_1 = require("./logger");
class HttpProxyMiddleware {
constructor(options) {
this.wsInternalSubscribed = false;
this.serverOnCloseSubscribed = false;
// https://github.com/Microsoft/TypeScript/wiki/'this'-in-TypeScript#red-flags-for-this
this.middleware = (async (req, res, next) => {
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);
}
}
else {
next?.();
}
/**
* Get the server object to subscribe to server events;
* 'upgrade' for websocket and 'close' for graceful shutdown
*
* NOTE:
* req.socket: node >= 13
* req.connection: node < 13 (Remove this when node 12/13 support is dropped)
*/
const server = (req.socket ?? req.connection)?.server;
if (server && !this.serverOnCloseSubscribed) {
server.on('close', () => {
(0, debug_1.Debug)('server close signal received: closing proxy server');
this.proxy.close();
});
this.serverOnCloseSubscribed = true;
}
if (this.proxyOptions.ws === true) {
// use initial request to access the server object to subscribe to http upgrade event
this.catchUpgradeRequest(server);
}
});
this.catchUpgradeRequest = (server) => {
if (!this.wsInternalSubscribed) {
(0, debug_1.Debug)('subscribing to server upgrade event');
server.on('upgrade', this.handleUpgrade);
// prevent duplicate upgrade handling;
// in case external upgrade is also configured
this.wsInternalSubscribed = true;
}
};
this.handleUpgrade = async (req, socket, head) => {
try {
if (this.shouldProxy(this.proxyOptions.pathFilter, req)) {
const activeProxyOptions = await this.prepareProxyRequest(req);
this.proxy.ws(req, socket, head, activeProxyOptions);
(0, debug_1.Debug)('server upgrade event received. Proxying WebSocket');
}
}
catch (err) {
// This error does not include the URL as the fourth argument as we won't
// have the URL if `this.prepareProxyRequest` throws an error.
this.proxy.emit('error', err, req, socket);
}
};
/**
* Determine whether request should be proxied.
*/
this.shouldProxy = (pathFilter, req) => {
try {
return (0, path_filter_1.matchPathFilter)(pathFilter, req.url, req);
}
catch (err) {
(0, debug_1.Debug)('Error: matchPathFilter() called with request url: ', `"${req.url}"`);
this.logger.error(err);
return false;
}
};
/**
* Apply option.router and option.pathRewrite
* Order matters:
* Router uses original path for routing;
* NOT the modified path, after it has been rewritten by pathRewrite
* @param {Object} req
* @return {Object} proxy options
*/
this.prepareProxyRequest = async (req) => {
/**
* 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);
// Apply in order:
// 1. option.router
// 2. option.pathRewrite
await this.applyRouter(req, newProxyOptions);
await this.applyPathRewrite(req, this.pathRewriter);
return newProxyOptions;
};
// Modify option.target when router present.
this.applyRouter = async (req, options) => {
let newTarget;
if (options.router) {
newTarget = await Router.getTarget(req, options);
if (newTarget) {
(0, debug_1.Debug)('router new target: "%s"', newTarget);
options.target = newTarget;
}
}
};
// rewrite path
this.applyPathRewrite = async (req, pathRewriter) => {
if (pathRewriter) {
const path = await pathRewriter(req.url, req);
if (typeof path === 'string') {
(0, debug_1.Debug)('pathRewrite new path: %s', req.url);
req.url = path;
}
else {
(0, debug_1.Debug)('pathRewrite: no rewritten path found: %s', req.url);
}
}
};
(0, configuration_1.verifyConfig)(options);
this.proxyOptions = options;
this.logger = (0, logger_1.getLogger)(options);
(0, debug_1.Debug)(`create proxy server`);
this.proxy = httpProxy.createProxyServer({});
this.registerPlugins(this.proxy, this.proxyOptions);
this.pathRewriter = PathRewriter.createPathRewriter(this.proxyOptions.pathRewrite); // returns undefined when "pathRewrite" is not provided
// https://github.com/chimurai/http-proxy-middleware/issues/19
// expose function to upgrade externally
this.middleware.upgrade = (req, socket, head) => {
if (!this.wsInternalSubscribed) {
this.handleUpgrade(req, socket, head);
}
};
}
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;

View File

@@ -0,0 +1,11 @@
export * from './factory';
export * from './handlers';
export type { Plugin, Filter, Options, RequestHandler } from './types';
/**
* Default plugins
*/
export * from './plugins/default';
/**
* Legacy exports
*/
export * from './legacy';

26
datav/node_modules/http-proxy-middleware/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,26 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = 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) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./factory"), exports);
__exportStar(require("./handlers"), exports);
/**
* Default plugins
*/
__exportStar(require("./plugins/default"), exports);
/**
* Legacy exports
*/
__exportStar(require("./legacy"), exports);

View File

@@ -0,0 +1,12 @@
import { Filter, RequestHandler } from '../types';
import { LegacyOptions } from './types';
import type * as http from 'http';
/**
* @deprecated
* This function is deprecated and will be removed in a future version.
*
* Use {@link createProxyMiddleware} instead.
*/
export declare function legacyCreateProxyMiddleware<TReq = http.IncomingMessage, TRes = http.ServerResponse>(shortHand: string): RequestHandler<TReq, TRes>;
export declare function legacyCreateProxyMiddleware<TReq = http.IncomingMessage, TRes = http.ServerResponse>(legacyOptions: LegacyOptions<TReq, TRes>): RequestHandler<TReq, TRes>;
export declare function legacyCreateProxyMiddleware<TReq = http.IncomingMessage, TRes = http.ServerResponse>(legacyContext: Filter<TReq>, legacyOptions: LegacyOptions<TReq, TRes>): RequestHandler<TReq, TRes>;

View File

@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.legacyCreateProxyMiddleware = legacyCreateProxyMiddleware;
const factory_1 = require("../factory");
const debug_1 = require("../debug");
const options_adapter_1 = require("./options-adapter");
const debug = debug_1.Debug.extend('legacy-create-proxy-middleware');
function legacyCreateProxyMiddleware(legacyContext, legacyOptions) {
debug('init');
const options = (0, options_adapter_1.legacyOptionsAdapter)(legacyContext, legacyOptions);
const proxyMiddleware = (0, factory_1.createProxyMiddleware)(options);
// https://github.com/chimurai/http-proxy-middleware/pull/731/files#diff-07e6ad10bda0df091b737caed42767657cd0bd74a01246a1a0b7ab59c0f6e977L118
debug('add marker for patching req.url (old behavior)');
proxyMiddleware.__LEGACY_HTTP_PROXY_MIDDLEWARE__ = true;
return proxyMiddleware;
}

View File

@@ -0,0 +1 @@
export * from './public';

View File

@@ -0,0 +1,17 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = 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) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./public"), exports);

View File

@@ -0,0 +1,6 @@
import { Filter, Options } from '../types';
import { LegacyOptions } from './types';
/**
* Convert {@link LegacyOptions legacy Options} to new {@link Options}
*/
export declare function legacyOptionsAdapter<TReq, TRes>(legacyContext: Filter<TReq> | LegacyOptions<TReq, TRes>, legacyOptions: LegacyOptions<TReq, TRes>): Options<TReq, TRes>;

View File

@@ -0,0 +1,97 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.legacyOptionsAdapter = legacyOptionsAdapter;
const url = require("url");
const debug_1 = require("../debug");
const logger_1 = require("../logger");
const debug = debug_1.Debug.extend('legacy-options-adapter');
// https://github.com/chimurai/http-proxy-middleware/blob/7341704d0aa9d1606dfd37ebfdffddd34c894784/src/_handlers.ts#L20-L27
const proxyEventMap = {
onError: 'error',
onProxyReq: 'proxyReq',
onProxyRes: 'proxyRes',
onProxyReqWs: 'proxyReqWs',
onOpen: 'open',
onClose: 'close',
};
/**
* Convert {@link LegacyOptions legacy Options} to new {@link Options}
*/
function legacyOptionsAdapter(legacyContext, legacyOptions) {
let options = {};
let logger;
// https://github.com/chimurai/http-proxy-middleware/pull/716
if (typeof legacyContext === 'string' && !!url.parse(legacyContext).host) {
throw new Error(`Shorthand syntax is removed from legacyCreateProxyMiddleware().
Please use "legacyCreateProxyMiddleware({ target: 'http://www.example.org' })" instead.
More details: https://github.com/chimurai/http-proxy-middleware/blob/master/MIGRATION.md#removed-shorthand-usage
`);
}
// detect old "context" argument and convert to "options.pathFilter"
// https://github.com/chimurai/http-proxy-middleware/pull/722/files#diff-a2a171449d862fe29692ce031981047d7ab755ae7f84c707aef80701b3ea0c80L4
if (legacyContext && legacyOptions) {
debug('map legacy context/filter to options.pathFilter');
options = { ...legacyOptions, pathFilter: legacyContext };
logger = getLegacyLogger(options);
logger.warn(`[http-proxy-middleware] Legacy "context" argument is deprecated. Migrate your "context" to "options.pathFilter":
const options = {
pathFilter: '${legacyContext}',
}
More details: https://github.com/chimurai/http-proxy-middleware/blob/master/MIGRATION.md#removed-context-argument
`);
}
else if (legacyContext && !legacyOptions) {
options = { ...legacyContext };
logger = getLegacyLogger(options);
}
else {
logger = getLegacyLogger({});
}
// map old event names to new event names
// https://github.com/chimurai/http-proxy-middleware/pull/745/files#diff-c54113cf61ec99691748a3890bfbeb00e10efb3f0a76f03a0fd9ec49072e410aL48-L53
Object.entries(proxyEventMap).forEach(([legacyEventName, proxyEventName]) => {
if (options[legacyEventName]) {
options.on = { ...options.on };
options.on[proxyEventName] = options[legacyEventName];
debug('map legacy event "%s" to "on.%s"', legacyEventName, proxyEventName);
logger.warn(`[http-proxy-middleware] Legacy "${legacyEventName}" is deprecated. Migrate to "options.on.${proxyEventName}":
const options = {
on: {
${proxyEventName}: () => {},
},
}
More details: https://github.com/chimurai/http-proxy-middleware/blob/master/MIGRATION.md#refactored-proxy-events
`);
}
});
// map old logProvider to new logger
// https://github.com/chimurai/http-proxy-middleware/pull/749
const logProvider = options.logProvider && options.logProvider();
const logLevel = options.logLevel;
debug('legacy logLevel', logLevel);
debug('legacy logProvider: %O', logProvider);
if (typeof logLevel === 'string' && logLevel !== 'silent') {
debug('map "logProvider" to "logger"');
logger.warn(`[http-proxy-middleware] Legacy "logLevel" and "logProvider" are deprecated. Migrate to "options.logger":
const options = {
logger: console,
}
More details: https://github.com/chimurai/http-proxy-middleware/blob/master/MIGRATION.md#removed-logprovider-and-loglevel-options
`);
}
return options;
}
function getLegacyLogger(options) {
const legacyLogger = options.logProvider && options.logProvider();
if (legacyLogger) {
options.logger = legacyLogger;
}
return (0, logger_1.getLogger)(options);
}

View File

@@ -0,0 +1,2 @@
export { legacyCreateProxyMiddleware } from './create-proxy-middleware';
export { LegacyOptions } from './types';

View File

@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.legacyCreateProxyMiddleware = void 0;
var create_proxy_middleware_1 = require("./create-proxy-middleware");
Object.defineProperty(exports, "legacyCreateProxyMiddleware", { enumerable: true, get: function () { return create_proxy_middleware_1.legacyCreateProxyMiddleware; } });

View File

@@ -0,0 +1,111 @@
import type * as http from 'http';
import { Options } from '../types';
/**
* @deprecated
*
* Will be removed in a future version.
*/
export interface LegacyOptions<TReq = http.IncomingMessage, TRes = http.ServerResponse> extends Options<TReq, TRes> {
/**
* @deprecated
* Use `on.error` instead.
*
* @example
* ```js
* {
* on: {
* error: () => {}
* }
* ```
*/
onError?: (...args: any[]) => void;
/**
* @deprecated
* Use `on.proxyRes` instead.
*
* @example
* ```js
* {
* on: {
* proxyRes: () => {}
* }
* ```
*/
onProxyRes?: (...args: any[]) => void;
/**
* @deprecated
* Use `on.proxyReq` instead.
*
* @example
* ```js
* {
* on: {
* proxyReq: () => {}
* }
* ```
*/
onProxyReq?: (...args: any[]) => void;
/**
* @deprecated
* Use `on.proxyReqWs` instead.
*
* @example
* ```js
* {
* on: {
* proxyReqWs: () => {}
* }
* ```
*/
onProxyReqWs?: (...args: any[]) => void;
/**
* @deprecated
* Use `on.open` instead.
*
* @example
* ```js
* {
* on: {
* open: () => {}
* }
* ```
*/
onOpen?: (...args: any[]) => void;
/**
* @deprecated
* Use `on.close` instead.
*
* @example
* ```js
* {
* on: {
* close: () => {}
* }
* ```
*/
onClose?: (...args: any[]) => void;
/**
* @deprecated
* Use `logger` instead.
*
* @example
* ```js
* {
* logger: console
* }
* ```
*/
logProvider?: any;
/**
* @deprecated
* Use `logger` instead.
*
* @example
* ```js
* {
* logger: console
* }
* ```
*/
logLevel?: any;
}

View File

@@ -0,0 +1,2 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1,2 @@
import { Logger, Options } from './types';
export declare function getLogger(options: Options): Logger;

View File

@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLogger = getLogger;
/**
* Compatibility matrix
*
| 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
*/
const noopLogger = {
info: () => { },
warn: () => { },
error: () => { },
};
function getLogger(options) {
return options.logger || noopLogger;
}

View File

@@ -0,0 +1,3 @@
import type { Filter } from './types';
import type * as http from 'http';
export declare function matchPathFilter<TReq = http.IncomingMessage>(pathFilter: Filter<TReq> | undefined, uri: string | undefined, req: http.IncomingMessage): boolean;

View File

@@ -0,0 +1,80 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.matchPathFilter = matchPathFilter;
const isGlob = require("is-glob");
const micromatch = require("micromatch");
const url = require("url");
const errors_1 = require("./errors");
function matchPathFilter(pathFilter = '/', uri, req) {
// single path
if (isStringPath(pathFilter)) {
return matchSingleStringPath(pathFilter, uri);
}
// single glob path
if (isGlobPath(pathFilter)) {
return matchSingleGlobPath(pathFilter, uri);
}
// multi path
if (Array.isArray(pathFilter)) {
if (pathFilter.every(isStringPath)) {
return matchMultiPath(pathFilter, uri);
}
if (pathFilter.every(isGlobPath)) {
return matchMultiGlobPath(pathFilter, uri);
}
throw new Error(errors_1.ERRORS.ERR_CONTEXT_MATCHER_INVALID_ARRAY);
}
// custom matching
if (typeof pathFilter === 'function') {
const pathname = getUrlPathName(uri);
return pathFilter(pathname, req);
}
throw new Error(errors_1.ERRORS.ERR_CONTEXT_MATCHER_GENERIC);
}
/**
* @param {String} pathFilter '/api'
* @param {String} uri 'http://example.org/api/b/c/d.html'
* @return {Boolean}
*/
function matchSingleStringPath(pathFilter, uri) {
const pathname = getUrlPathName(uri);
return pathname?.indexOf(pathFilter) === 0;
}
function matchSingleGlobPath(pattern, uri) {
const pathname = getUrlPathName(uri);
const matches = micromatch([pathname], pattern);
return matches && matches.length > 0;
}
function matchMultiGlobPath(patternList, uri) {
return matchSingleGlobPath(patternList, uri);
}
/**
* @param {String} pathFilterList ['/api', '/ajax']
* @param {String} uri 'http://example.org/api/b/c/d.html'
* @return {Boolean}
*/
function matchMultiPath(pathFilterList, uri) {
let isMultiPath = false;
for (const context of pathFilterList) {
if (matchSingleStringPath(context, uri)) {
isMultiPath = true;
break;
}
}
return isMultiPath;
}
/**
* Parses URI and returns RFC 3986 path
*
* @param {String} uri from req.url
* @return {String} RFC 3986 path
*/
function getUrlPathName(uri) {
return uri && url.parse(uri).pathname;
}
function isStringPath(pathFilter) {
return typeof pathFilter === 'string' && !isGlob(pathFilter);
}
function isGlobPath(pathFilter) {
return isGlob(pathFilter);
}

View File

@@ -0,0 +1,7 @@
/**
* Create rewrite function, to cache parsed rewrite rules.
*
* @param {Object} rewriteConfig
* @return {Function} Function to rewrite paths; This function should accept `path` (request.url) as parameter
*/
export declare function createPathRewriter(rewriteConfig: any): any;

View File

@@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createPathRewriter = createPathRewriter;
const is_plain_object_1 = require("is-plain-object");
const errors_1 = require("./errors");
const debug_1 = require("./debug");
const debug = debug_1.Debug.extend('path-rewriter');
/**
* Create rewrite function, to cache parsed rewrite rules.
*
* @param {Object} rewriteConfig
* @return {Function} Function to rewrite paths; This function should accept `path` (request.url) as parameter
*/
function createPathRewriter(rewriteConfig) {
let rulesCache;
if (!isValidRewriteConfig(rewriteConfig)) {
return;
}
if (typeof rewriteConfig === 'function') {
const customRewriteFn = rewriteConfig;
return customRewriteFn;
}
else {
rulesCache = parsePathRewriteRules(rewriteConfig);
return rewritePath;
}
function rewritePath(path) {
let result = path;
for (const rule of rulesCache) {
if (rule.regex.test(path)) {
result = result.replace(rule.regex, rule.value);
debug('rewriting path from "%s" to "%s"', path, result);
break;
}
}
return result;
}
}
function isValidRewriteConfig(rewriteConfig) {
if (typeof rewriteConfig === 'function') {
return true;
}
else if ((0, is_plain_object_1.isPlainObject)(rewriteConfig)) {
return Object.keys(rewriteConfig).length !== 0;
}
else if (rewriteConfig === undefined || rewriteConfig === null) {
return false;
}
else {
throw new Error(errors_1.ERRORS.ERR_PATH_REWRITER_CONFIG);
}
}
function parsePathRewriteRules(rewriteConfig) {
const rules = [];
if ((0, is_plain_object_1.isPlainObject)(rewriteConfig)) {
for (const [key, value] of Object.entries(rewriteConfig)) {
rules.push({
regex: new RegExp(key),
value: value,
});
debug('rewrite rule created: "%s" ~> "%s"', key, value);
}
}
return rules;
}

View File

@@ -0,0 +1,6 @@
import { Plugin } from '../../types';
/**
* Subscribe to {@link https://www.npmjs.com/package/http-proxy#listening-for-proxy-events http-proxy error events} to prevent server from crashing.
* Errors are logged with {@link https://www.npmjs.com/package/debug debug} library.
*/
export declare const debugProxyErrorsPlugin: Plugin;

View File

@@ -0,0 +1,61 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.debugProxyErrorsPlugin = void 0;
const debug_1 = require("../../debug");
const debug = debug_1.Debug.extend('debug-proxy-errors-plugin');
/**
* Subscribe to {@link https://www.npmjs.com/package/http-proxy#listening-for-proxy-events http-proxy error events} to prevent server from crashing.
* Errors are logged with {@link https://www.npmjs.com/package/debug debug} library.
*/
const debugProxyErrorsPlugin = (proxyServer) => {
/**
* http-proxy doesn't handle any errors by default (https://github.com/http-party/node-http-proxy#listening-for-proxy-events)
* Prevent server from crashing when http-proxy errors (uncaught errors)
*/
proxyServer.on('error', (error, req, res, target) => {
debug(`http-proxy error event: \n%O`, error);
});
proxyServer.on('proxyReq', (proxyReq, req, socket) => {
socket.on('error', (error) => {
debug('Socket error in proxyReq event: \n%O', error);
});
});
/**
* Fix SSE close events
* @link https://github.com/chimurai/http-proxy-middleware/issues/678
* @link https://github.com/http-party/node-http-proxy/issues/1520#issue-877626125
*/
proxyServer.on('proxyRes', (proxyRes, req, res) => {
res.on('close', () => {
if (!res.writableEnded) {
debug('Destroying proxyRes in proxyRes close event');
proxyRes.destroy();
}
});
});
/**
* Fix crash when target server restarts
* https://github.com/chimurai/http-proxy-middleware/issues/476#issuecomment-746329030
* https://github.com/webpack/webpack-dev-server/issues/1642#issuecomment-790602225
*/
proxyServer.on('proxyReqWs', (proxyReq, req, socket) => {
socket.on('error', (error) => {
debug('Socket error in proxyReqWs event: \n%O', error);
});
});
proxyServer.on('open', (proxySocket) => {
proxySocket.on('error', (error) => {
debug('Socket error in open event: \n%O', error);
});
});
proxyServer.on('close', (req, socket, head) => {
socket.on('error', (error) => {
debug('Socket error in close event: \n%O', error);
});
});
// https://github.com/webpack/webpack-dev-server/issues/1642#issuecomment-1103136590
proxyServer.on('econnreset', (error, req, res, target) => {
debug(`http-proxy econnreset event: \n%O`, error);
});
};
exports.debugProxyErrorsPlugin = debugProxyErrorsPlugin;

View File

@@ -0,0 +1,2 @@
import { Plugin } from '../../types';
export declare const errorResponsePlugin: Plugin;

View File

@@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.errorResponsePlugin = void 0;
const status_code_1 = require("../../status-code");
function isResponseLike(obj) {
return obj && typeof obj.writeHead === 'function';
}
function isSocketLike(obj) {
return obj && typeof obj.write === 'function' && !('writeHead' in obj);
}
const errorResponsePlugin = (proxyServer, options) => {
proxyServer.on('error', (err, req, res, target) => {
// Re-throw error. Not recoverable since req & res are empty.
if (!req && !res) {
throw err; // "Error: Must provide a proper URL as target"
}
if (isResponseLike(res)) {
if (!res.headersSent) {
const statusCode = (0, status_code_1.getStatusCode)(err.code);
res.writeHead(statusCode);
}
const host = req.headers && req.headers.host;
res.end(`Error occurred while trying to proxy: ${host}${req.url}`);
}
else if (isSocketLike(res)) {
res.destroy();
}
});
};
exports.errorResponsePlugin = errorResponsePlugin;

View File

@@ -0,0 +1,4 @@
export * from './debug-proxy-errors-plugin';
export * from './error-response-plugin';
export * from './logger-plugin';
export * from './proxy-events';

View File

@@ -0,0 +1,20 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = 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) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(require("./debug-proxy-errors-plugin"), exports);
__exportStar(require("./error-response-plugin"), exports);
__exportStar(require("./logger-plugin"), exports);
__exportStar(require("./proxy-events"), exports);

View File

@@ -0,0 +1,2 @@
import { Plugin } from '../../types';
export declare const loggerPlugin: Plugin;

View File

@@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.loggerPlugin = void 0;
const url_1 = require("url");
const logger_1 = require("../../logger");
const logger_plugin_1 = require("../../utils/logger-plugin");
const loggerPlugin = (proxyServer, options) => {
const logger = (0, logger_1.getLogger)(options);
proxyServer.on('error', (err, req, res, target) => {
const hostname = req?.headers?.host;
const requestHref = `${hostname}${req?.url}`;
const targetHref = `${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
logger.error(errorMessage, requestHref, targetHref, err.code || err, errReference);
});
/**
* Log request and response
* @example
* ```shell
* [HPM] GET /users/ -> http://jsonplaceholder.typicode.com/users/ [304]
* ```
*/
proxyServer.on('proxyRes', (proxyRes, req, res) => {
// BrowserSync uses req.originalUrl
// Next.js doesn't have req.baseUrl
const originalUrl = req.originalUrl ?? `${req.baseUrl || ''}${req.url}`;
// construct targetUrl
let target;
try {
const port = (0, logger_plugin_1.getPort)(proxyRes.req?.agent?.sockets);
const obj = {
protocol: proxyRes.req.protocol,
host: proxyRes.req.host,
pathname: proxyRes.req.path,
};
target = new url_1.URL(`${obj.protocol}//${obj.host}${obj.pathname}`);
if (port) {
target.port = port;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
}
catch (err) {
// nock issue (https://github.com/chimurai/http-proxy-middleware/issues/1035)
// fallback to old implementation (less correct - without port)
target = new url_1.URL(options.target);
target.pathname = proxyRes.req.path;
}
const targetUrl = target.toString();
const exchange = `[HPM] ${req.method} ${originalUrl} -> ${targetUrl} [${proxyRes.statusCode}]`;
logger.info(exchange);
});
/**
* When client opens WebSocket connection
*/
proxyServer.on('open', (socket) => {
logger.info('[HPM] Client connected: %o', socket.address());
});
/**
* When client closes WebSocket connection
*/
proxyServer.on('close', (req, proxySocket, proxyHead) => {
logger.info('[HPM] Client disconnected: %o', proxySocket.address());
});
};
exports.loggerPlugin = loggerPlugin;

View File

@@ -0,0 +1,22 @@
import { Plugin } from '../../types';
/**
* Implements option.on object to subscribe to http-proxy events.
*
* @example
* ```js
* createProxyMiddleware({
* on: {
* error: (error, req, res, target) => {},
* proxyReq: (proxyReq, req, res, options) => {},
* proxyReqWs: (proxyReq, req, socket, options) => {},
* proxyRes: (proxyRes, req, res) => {},
* open: (proxySocket) => {},
* close: (proxyRes, proxySocket, proxyHead) => {},
* start: (req, res, target) => {},
* end: (req, res, proxyRes) => {},
* econnreset: (error, req, res, target) => {},
* }
* });
* ```
*/
export declare const proxyEventsPlugin: Plugin;

View File

@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.proxyEventsPlugin = void 0;
const debug_1 = require("../../debug");
const function_1 = require("../../utils/function");
const debug = debug_1.Debug.extend('proxy-events-plugin');
/**
* Implements option.on object to subscribe to http-proxy events.
*
* @example
* ```js
* createProxyMiddleware({
* on: {
* error: (error, req, res, target) => {},
* proxyReq: (proxyReq, req, res, options) => {},
* proxyReqWs: (proxyReq, req, socket, options) => {},
* proxyRes: (proxyRes, req, res) => {},
* open: (proxySocket) => {},
* close: (proxyRes, proxySocket, proxyHead) => {},
* start: (req, res, target) => {},
* end: (req, res, proxyRes) => {},
* econnreset: (error, req, res, target) => {},
* }
* });
* ```
*/
const proxyEventsPlugin = (proxyServer, options) => {
Object.entries(options.on || {}).forEach(([eventName, handler]) => {
debug(`register event handler: "${eventName}" -> "${(0, function_1.getFunctionName)(handler)}"`);
proxyServer.on(eventName, handler);
});
};
exports.proxyEventsPlugin = proxyEventsPlugin;

View File

@@ -0,0 +1 @@
export declare function getTarget(req: any, config: any): Promise<any>;

View File

@@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTarget = getTarget;
const is_plain_object_1 = require("is-plain-object");
const debug_1 = require("./debug");
const debug = debug_1.Debug.extend('router');
async function getTarget(req, config) {
let newTarget;
const router = config.router;
if ((0, is_plain_object_1.isPlainObject)(router)) {
newTarget = getTargetFromProxyTable(req, router);
}
else if (typeof router === 'function') {
newTarget = await router(req);
}
return newTarget;
}
function getTargetFromProxyTable(req, table) {
let result;
const host = req.headers.host;
const path = req.url;
const hostAndPath = host + path;
for (const [key, value] of Object.entries(table)) {
if (containsPath(key)) {
if (hostAndPath.indexOf(key) > -1) {
// match 'localhost:3000/api'
result = value;
debug('match: "%s" -> "%s"', key, result);
break;
}
}
else {
if (key === host) {
// match 'localhost:3000'
result = value;
debug('match: "%s" -> "%s"', host, result);
break;
}
}
}
return result;
}
function containsPath(v) {
return v.indexOf('/') > -1;
}

View File

@@ -0,0 +1 @@
export declare function getStatusCode(errorCode: string): number;

View File

@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getStatusCode = getStatusCode;
function getStatusCode(errorCode) {
let statusCode;
if (/HPE_INVALID/.test(errorCode)) {
statusCode = 502;
}
else {
switch (errorCode) {
case 'ECONNRESET':
case 'ENOTFOUND':
case 'ECONNREFUSED':
case 'ETIMEDOUT':
statusCode = 504;
break;
default:
statusCode = 500;
break;
}
}
return statusCode;
}

View File

@@ -0,0 +1,122 @@
/**
* Based on definition by DefinitelyTyped:
* https://github.com/DefinitelyTyped/DefinitelyTyped/blob/6f529c6c67a447190f86bfbf894d1061e41e07b7/types/http-proxy-middleware/index.d.ts
*/
import type * as http from 'http';
import type * as httpProxy from 'http-proxy';
import type * as net from 'net';
export type NextFunction<T = (err?: any) => void> = T;
export interface RequestHandler<TReq = http.IncomingMessage, TRes = http.ServerResponse, TNext = NextFunction> {
(req: TReq, res: TRes, next?: TNext): Promise<void>;
upgrade: (req: http.IncomingMessage, socket: net.Socket, head: Buffer) => void;
}
export type Filter<TReq = http.IncomingMessage> = string | string[] | ((pathname: string, req: TReq) => boolean);
export interface Plugin<TReq = http.IncomingMessage, TRes = http.ServerResponse> {
(proxyServer: httpProxy<TReq, TRes>, options: Options<TReq, TRes>): void;
}
export interface OnProxyEvent<TReq = http.IncomingMessage, TRes = http.ServerResponse> {
error?: httpProxy.ErrorCallback<Error, TReq, TRes>;
proxyReq?: httpProxy.ProxyReqCallback<http.ClientRequest, TReq, TRes>;
proxyReqWs?: httpProxy.ProxyReqWsCallback<http.ClientRequest, TReq>;
proxyRes?: httpProxy.ProxyResCallback<TReq, TRes>;
open?: httpProxy.OpenCallback;
close?: httpProxy.CloseCallback<TReq>;
start?: httpProxy.StartCallback<TReq, TRes>;
end?: httpProxy.EndCallback<TReq, TRes>;
econnreset?: httpProxy.EconnresetCallback<Error, TReq, TRes>;
}
export type Logger = Pick<Console, 'info' | 'warn' | 'error'>;
export interface Options<TReq = http.IncomingMessage, TRes = http.ServerResponse> 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.
* @link https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/pathFilter.md
* @since v3.0.0
*/
pathFilter?: Filter<TReq>;
/**
* Modify request paths before requests are send to the target.
* @example
* ```js
* createProxyMiddleware({
* pathRewrite: {
* '^/api/old-path': '/api/new-path', // rewrite path
* }
* });
* ```
* @link https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/pathRewrite.md
*/
pathRewrite?: {
[regexp: string]: string;
} | ((path: string, req: TReq) => string | undefined) | ((path: string, req: TReq) => 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);
* });
* }]
* });
* ```
* @link https://github.com/chimurai/http-proxy-middleware#plugins-array
* @since v3.0.0
*/
plugins?: Plugin<TReq, TRes>[];
/**
* Eject pre-configured plugins.
* NOTE: register your own error handlers to prevent server from crashing.
*
* @link https://github.com/chimurai/http-proxy-middleware#ejectplugins-boolean-default-false
* @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);
* }
* }
* });
* ```
* @link https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/proxy-events.md
* @since v3.0.0
*/
on?: OnProxyEvent<TReq, TRes>;
/**
* Dynamically set the {@link Options.target `options.target`}.
* @example
* ```js
* createProxyMiddleware({
* router: async (req) => {
* return 'http://127:0.0.1:3000';
* }
* });
* ```
* @link https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/router.md
*/
router?: {
[hostOrPath: string]: httpProxy.ServerOptions['target'];
} | ((req: TReq) => httpProxy.ServerOptions['target']) | ((req: TReq) => Promise<httpProxy.ServerOptions['target']>);
/**
* Log information from http-proxy-middleware
* @example
* ```js
* createProxyMiddleware({
* logger: console
* });
* ```
* @link https://github.com/chimurai/http-proxy-middleware/blob/master/recipes/logger.md
* @since v3.0.0
*/
logger?: Logger | any;
}

View File

@@ -0,0 +1,6 @@
"use strict";
/**
* Based on definition by DefinitelyTyped:
* https://github.com/DefinitelyTyped/DefinitelyTyped/blob/6f529c6c67a447190f86bfbf894d1061e41e07b7/types/http-proxy-middleware/index.d.ts
*/
Object.defineProperty(exports, "__esModule", { value: true });

View File

@@ -0,0 +1 @@
export declare function getFunctionName(fn: Function): string;

View File

@@ -0,0 +1,7 @@
"use strict";
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
Object.defineProperty(exports, "__esModule", { value: true });
exports.getFunctionName = getFunctionName;
function getFunctionName(fn) {
return fn.name || '[anonymous Function]';
}

View File

@@ -0,0 +1,7 @@
import type { Agent } from 'node:http';
export type Sockets = Pick<Agent, 'sockets'>;
/**
* Get port from target
* Using proxyRes.req.agent.sockets to determine the target port
*/
export declare function getPort(sockets?: Sockets): string | undefined;

View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPort = getPort;
/**
* Get port from target
* Using proxyRes.req.agent.sockets to determine the target port
*/
function getPort(sockets) {
return Object.keys(sockets || {})?.[0]?.split(':')[1];
}