http-proxy-middleware 3.0.5 → 4.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -49
- package/dist/configuration.d.ts +3 -2
- package/dist/configuration.js +3 -6
- package/dist/debug.d.ts +1 -1
- package/dist/debug.js +2 -5
- package/dist/errors.js +2 -5
- package/dist/factory.d.ts +3 -3
- package/dist/factory.js +3 -6
- package/dist/get-plugins.d.ts +3 -2
- package/dist/get-plugins.js +4 -7
- package/dist/handlers/fix-request-body.d.ts +1 -1
- package/dist/handlers/fix-request-body.js +21 -7
- package/dist/handlers/index.d.ts +1 -1
- package/dist/handlers/index.js +1 -17
- package/dist/handlers/public.d.ts +2 -2
- package/dist/handlers/public.js +2 -7
- package/dist/handlers/response-interceptor.d.ts +3 -3
- package/dist/handlers/response-interceptor.js +6 -9
- package/dist/http-proxy-middleware.d.ts +4 -3
- package/dist/http-proxy-middleware.js +165 -140
- package/dist/index.d.ts +4 -8
- package/dist/index.js +3 -23
- package/dist/logger.d.ts +1 -1
- package/dist/logger.js +1 -4
- package/dist/path-filter.d.ts +3 -3
- package/dist/path-filter.js +7 -11
- package/dist/path-rewriter.js +8 -11
- package/dist/plugins/default/debug-proxy-errors-plugin.d.ts +1 -1
- package/dist/plugins/default/debug-proxy-errors-plugin.js +3 -7
- package/dist/plugins/default/error-response-plugin.d.ts +1 -1
- package/dist/plugins/default/error-response-plugin.js +6 -9
- package/dist/plugins/default/index.d.ts +4 -4
- package/dist/plugins/default/index.js +4 -20
- package/dist/plugins/default/logger-plugin.d.ts +1 -1
- package/dist/plugins/default/logger-plugin.js +8 -12
- package/dist/plugins/default/proxy-events.d.ts +1 -1
- package/dist/plugins/default/proxy-events.js +20 -12
- package/dist/router.js +5 -8
- package/dist/status-code.js +1 -4
- package/dist/types.d.ts +21 -21
- package/dist/types.js +1 -6
- package/dist/utils/function.js +1 -4
- package/dist/utils/logger-plugin.js +1 -4
- package/dist/utils/sanitize.d.ts +1 -0
- package/dist/utils/sanitize.js +3 -0
- package/package.json +44 -36
- package/dist/legacy/create-proxy-middleware.d.ts +0 -12
- package/dist/legacy/create-proxy-middleware.js +0 -16
- package/dist/legacy/index.d.ts +0 -1
- package/dist/legacy/index.js +0 -17
- package/dist/legacy/options-adapter.d.ts +0 -6
- package/dist/legacy/options-adapter.js +0 -97
- package/dist/legacy/public.d.ts +0 -2
- package/dist/legacy/public.js +0 -5
- package/dist/legacy/types.d.ts +0 -111
- package/dist/legacy/types.js +0 -2
|
@@ -1,161 +1,186 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
import { createProxyServer } from 'httpxy';
|
|
2
|
+
import { verifyConfig } from './configuration.js';
|
|
3
|
+
import { Debug as debug } from './debug.js';
|
|
4
|
+
import { getPlugins } from './get-plugins.js';
|
|
5
|
+
import { getLogger } from './logger.js';
|
|
6
|
+
import { matchPathFilter } from './path-filter.js';
|
|
7
|
+
import * as PathRewriter from './path-rewriter.js';
|
|
8
|
+
import * as Router from './router.js';
|
|
9
|
+
import { getFunctionName } from './utils/function.js';
|
|
10
|
+
export class HttpProxyMiddleware {
|
|
11
|
+
wsInternalSubscribed = false;
|
|
12
|
+
serverOnCloseSubscribed = false;
|
|
13
|
+
proxyOptions;
|
|
14
|
+
proxy;
|
|
15
|
+
pathRewriter;
|
|
16
|
+
logger;
|
|
14
17
|
constructor(options) {
|
|
15
|
-
|
|
16
|
-
this.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
catch (err) {
|
|
26
|
-
next?.(err);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
next?.();
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Get the server object to subscribe to server events;
|
|
34
|
-
* 'upgrade' for websocket and 'close' for graceful shutdown
|
|
35
|
-
*
|
|
36
|
-
* NOTE:
|
|
37
|
-
* req.socket: node >= 13
|
|
38
|
-
* req.connection: node < 13 (Remove this when node 12/13 support is dropped)
|
|
39
|
-
*/
|
|
40
|
-
const server = (req.socket ?? req.connection)?.server;
|
|
41
|
-
if (server && !this.serverOnCloseSubscribed) {
|
|
42
|
-
server.on('close', () => {
|
|
43
|
-
(0, debug_1.Debug)('server close signal received: closing proxy server');
|
|
44
|
-
this.proxy.close();
|
|
45
|
-
});
|
|
46
|
-
this.serverOnCloseSubscribed = true;
|
|
47
|
-
}
|
|
48
|
-
if (this.proxyOptions.ws === true) {
|
|
49
|
-
// use initial request to access the server object to subscribe to http upgrade event
|
|
50
|
-
this.catchUpgradeRequest(server);
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
this.catchUpgradeRequest = (server) => {
|
|
18
|
+
verifyConfig(options);
|
|
19
|
+
this.proxyOptions = options;
|
|
20
|
+
this.logger = getLogger(options);
|
|
21
|
+
debug(`create proxy server`);
|
|
22
|
+
this.proxy = createProxyServer({});
|
|
23
|
+
this.registerPlugins(this.proxy, this.proxyOptions);
|
|
24
|
+
this.pathRewriter = PathRewriter.createPathRewriter(this.proxyOptions.pathRewrite); // returns undefined when "pathRewrite" is not provided
|
|
25
|
+
// https://github.com/chimurai/http-proxy-middleware/issues/19
|
|
26
|
+
// expose function to upgrade externally
|
|
27
|
+
this.middleware.upgrade = (req, socket, head) => {
|
|
54
28
|
if (!this.wsInternalSubscribed) {
|
|
55
|
-
(
|
|
56
|
-
server.on('upgrade', this.handleUpgrade);
|
|
57
|
-
// prevent duplicate upgrade handling;
|
|
58
|
-
// in case external upgrade is also configured
|
|
59
|
-
this.wsInternalSubscribed = true;
|
|
29
|
+
this.handleUpgrade(req, socket, head);
|
|
60
30
|
}
|
|
61
31
|
};
|
|
62
|
-
|
|
32
|
+
}
|
|
33
|
+
// https://github.com/Microsoft/TypeScript/wiki/'this'-in-TypeScript#red-flags-for-this
|
|
34
|
+
middleware = (async (req, res, next) => {
|
|
35
|
+
if (this.shouldProxy(this.proxyOptions.pathFilter, req)) {
|
|
36
|
+
let activeProxyOptions;
|
|
63
37
|
try {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
38
|
+
// Preparation Phase: Apply router and path rewriter.
|
|
39
|
+
activeProxyOptions = await this.prepareProxyRequest(req);
|
|
40
|
+
// [Smoking Gun] httpxy is inconsistent with error handling:
|
|
41
|
+
// 1. If target is missing (here), it emits 'error' but returns a boolean (bypassing our catch/next).
|
|
42
|
+
// 2. If a network error occurs (in proxy.web), it rejects the promise but SKIPS emitting 'error'.
|
|
43
|
+
// We manually throw here to force Case 1 into the catch block so next(err) is called for Express.
|
|
44
|
+
if (!activeProxyOptions.target && !activeProxyOptions.forward) {
|
|
45
|
+
throw new Error('Must provide a proper URL as target');
|
|
68
46
|
}
|
|
69
47
|
}
|
|
70
48
|
catch (err) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
this.proxy.emit('error', err, req, socket);
|
|
49
|
+
next?.(err);
|
|
50
|
+
return;
|
|
74
51
|
}
|
|
75
|
-
};
|
|
76
|
-
/**
|
|
77
|
-
* Determine whether request should be proxied.
|
|
78
|
-
*/
|
|
79
|
-
this.shouldProxy = (pathFilter, req) => {
|
|
80
52
|
try {
|
|
81
|
-
|
|
53
|
+
// Proxying Phase: Handle the actual web request.
|
|
54
|
+
debug(`proxy request to target: %O`, activeProxyOptions.target);
|
|
55
|
+
await this.proxy.web(req, res, activeProxyOptions);
|
|
82
56
|
}
|
|
83
57
|
catch (err) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
58
|
+
// Manually emit 'error' event because httpxy's promise-based API does not emit it automatically.
|
|
59
|
+
// This is crucial for backward compatibility with HPM plugins (like error-response-plugin)
|
|
60
|
+
// and custom listeners registered via the 'on: { error: ... }' option.
|
|
61
|
+
/**
|
|
62
|
+
* TODO: Ideally, TReq and TRes should be restricted via "TReq extends http.IncomingMessage = http.IncomingMessage"
|
|
63
|
+
* and "TRes extends http.ServerResponse = http.ServerResponse", which allows us to avoid the "req as TReq" below.
|
|
64
|
+
*
|
|
65
|
+
* However, making TReq and TRes constrained types may cause a breaking change for TypeScript users downstream.
|
|
66
|
+
* So we leave this as a TODO for now, and revisit it in a future major release.
|
|
67
|
+
*/
|
|
68
|
+
this.proxy.emit('error', err, req, res, activeProxyOptions.target);
|
|
69
|
+
next?.(err);
|
|
87
70
|
}
|
|
88
|
-
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
next?.();
|
|
74
|
+
}
|
|
89
75
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
* Router uses original path for routing;
|
|
93
|
-
* NOT the modified path, after it has been rewritten by pathRewrite
|
|
94
|
-
* @param {Object} req
|
|
95
|
-
* @return {Object} proxy options
|
|
76
|
+
* Get the server object to subscribe to server events;
|
|
77
|
+
* 'upgrade' for websocket and 'close' for graceful shutdown
|
|
96
78
|
*/
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return newProxyOptions;
|
|
113
|
-
};
|
|
114
|
-
// Modify option.target when router present.
|
|
115
|
-
this.applyRouter = async (req, options) => {
|
|
116
|
-
let newTarget;
|
|
117
|
-
if (options.router) {
|
|
118
|
-
newTarget = await Router.getTarget(req, options);
|
|
119
|
-
if (newTarget) {
|
|
120
|
-
(0, debug_1.Debug)('router new target: "%s"', newTarget);
|
|
121
|
-
options.target = newTarget;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
// rewrite path
|
|
126
|
-
this.applyPathRewrite = async (req, pathRewriter) => {
|
|
127
|
-
if (pathRewriter) {
|
|
128
|
-
const path = await pathRewriter(req.url, req);
|
|
129
|
-
if (typeof path === 'string') {
|
|
130
|
-
(0, debug_1.Debug)('pathRewrite new path: %s', req.url);
|
|
131
|
-
req.url = path;
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
(0, debug_1.Debug)('pathRewrite: no rewritten path found: %s', req.url);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
(0, configuration_1.verifyConfig)(options);
|
|
139
|
-
this.proxyOptions = options;
|
|
140
|
-
this.logger = (0, logger_1.getLogger)(options);
|
|
141
|
-
(0, debug_1.Debug)(`create proxy server`);
|
|
142
|
-
this.proxy = httpProxy.createProxyServer({});
|
|
143
|
-
this.registerPlugins(this.proxy, this.proxyOptions);
|
|
144
|
-
this.pathRewriter = PathRewriter.createPathRewriter(this.proxyOptions.pathRewrite); // returns undefined when "pathRewrite" is not provided
|
|
145
|
-
// https://github.com/chimurai/http-proxy-middleware/issues/19
|
|
146
|
-
// expose function to upgrade externally
|
|
147
|
-
this.middleware.upgrade = (req, socket, head) => {
|
|
148
|
-
if (!this.wsInternalSubscribed) {
|
|
149
|
-
this.handleUpgrade(req, socket, head);
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
}
|
|
79
|
+
const server = req.socket?.server;
|
|
80
|
+
if (server && !this.serverOnCloseSubscribed) {
|
|
81
|
+
server.on('close', () => {
|
|
82
|
+
debug('server close signal received: closing proxy server');
|
|
83
|
+
this.proxy.close(() => {
|
|
84
|
+
debug('proxy server closed');
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
this.serverOnCloseSubscribed = true;
|
|
88
|
+
}
|
|
89
|
+
if (this.proxyOptions.ws === true && server) {
|
|
90
|
+
// use initial request to access the server object to subscribe to http upgrade event
|
|
91
|
+
this.catchUpgradeRequest(server);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
153
94
|
registerPlugins(proxy, options) {
|
|
154
|
-
const plugins =
|
|
95
|
+
const plugins = getPlugins(options);
|
|
155
96
|
plugins.forEach((plugin) => {
|
|
156
|
-
(
|
|
97
|
+
debug(`register plugin: "${getFunctionName(plugin)}"`);
|
|
157
98
|
plugin(proxy, options);
|
|
158
99
|
});
|
|
159
100
|
}
|
|
101
|
+
catchUpgradeRequest = (server) => {
|
|
102
|
+
if (!this.wsInternalSubscribed) {
|
|
103
|
+
debug('subscribing to server upgrade event');
|
|
104
|
+
server.on('upgrade', this.handleUpgrade);
|
|
105
|
+
// prevent duplicate upgrade handling;
|
|
106
|
+
// in case external upgrade is also configured
|
|
107
|
+
this.wsInternalSubscribed = true;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
handleUpgrade = async (req, socket, head) => {
|
|
111
|
+
try {
|
|
112
|
+
if (this.shouldProxy(this.proxyOptions.pathFilter, req)) {
|
|
113
|
+
const proxiedReq = req;
|
|
114
|
+
const activeProxyOptions = await this.prepareProxyRequest(proxiedReq);
|
|
115
|
+
await this.proxy.ws(proxiedReq, socket, activeProxyOptions, head);
|
|
116
|
+
debug('server upgrade event received. Proxying WebSocket');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
// This error does not include the URL as the fourth argument as we won't
|
|
121
|
+
// have the URL if `this.prepareProxyRequest` throws an error.
|
|
122
|
+
/**
|
|
123
|
+
* TODO: Ideally, TReq and TRes should be restricted via "TReq extends http.IncomingMessage = http.IncomingMessage"
|
|
124
|
+
* and "TRes extends http.ServerResponse = http.ServerResponse", which allows us to avoid the "req as TReq" below.
|
|
125
|
+
*
|
|
126
|
+
* However, making TReq and TRes constrained types may cause a breaking change for TypeScript users downstream.
|
|
127
|
+
* So we leave this as a TODO for now, and revisit it in a future major release.
|
|
128
|
+
*/
|
|
129
|
+
this.proxy.emit('error', err, req, socket);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Determine whether request should be proxied.
|
|
134
|
+
*/
|
|
135
|
+
shouldProxy = (pathFilter, req) => {
|
|
136
|
+
try {
|
|
137
|
+
return matchPathFilter(pathFilter, req.url, req);
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
debug('Error: matchPathFilter() called with request url: ', `"${req.url}"`);
|
|
141
|
+
this.logger.error(err);
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Apply option.router and option.pathRewrite
|
|
147
|
+
* Order matters:
|
|
148
|
+
* Router uses original path for routing;
|
|
149
|
+
* NOT the modified path, after it has been rewritten by pathRewrite
|
|
150
|
+
* @param {Object} req
|
|
151
|
+
* @return {Object} proxy options
|
|
152
|
+
*/
|
|
153
|
+
prepareProxyRequest = async (req) => {
|
|
154
|
+
const newProxyOptions = Object.assign({}, this.proxyOptions);
|
|
155
|
+
// Apply in order:
|
|
156
|
+
// 1. option.router
|
|
157
|
+
// 2. option.pathRewrite
|
|
158
|
+
await this.applyRouter(req, newProxyOptions);
|
|
159
|
+
await this.applyPathRewrite(req, this.pathRewriter);
|
|
160
|
+
return newProxyOptions;
|
|
161
|
+
};
|
|
162
|
+
// Modify option.target when router present.
|
|
163
|
+
applyRouter = async (req, options) => {
|
|
164
|
+
let newTarget;
|
|
165
|
+
if (options.router) {
|
|
166
|
+
newTarget = await Router.getTarget(req, options);
|
|
167
|
+
if (newTarget) {
|
|
168
|
+
debug('router new target: "%s"', newTarget);
|
|
169
|
+
options.target = newTarget;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
// rewrite path
|
|
174
|
+
applyPathRewrite = async (req, pathRewriter) => {
|
|
175
|
+
if (pathRewriter) {
|
|
176
|
+
const path = await pathRewriter(req.url, req);
|
|
177
|
+
if (typeof path === 'string') {
|
|
178
|
+
debug('pathRewrite new path: %s', path);
|
|
179
|
+
req.url = path;
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
debug('pathRewrite: no rewritten path found: %s', req.url);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
};
|
|
160
186
|
}
|
|
161
|
-
exports.HttpProxyMiddleware = HttpProxyMiddleware;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
export * from './factory';
|
|
2
|
-
export * from './handlers';
|
|
3
|
-
export type { Plugin, Filter, Options, RequestHandler } from './types';
|
|
1
|
+
export * from './factory.js';
|
|
2
|
+
export * from './handlers/index.js';
|
|
3
|
+
export type { Plugin, Filter, Options, RequestHandler } from './types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Default plugins
|
|
6
6
|
*/
|
|
7
|
-
export * from './plugins/default';
|
|
8
|
-
/**
|
|
9
|
-
* Legacy exports
|
|
10
|
-
*/
|
|
11
|
-
export * from './legacy';
|
|
7
|
+
export * from './plugins/default/index.js';
|
package/dist/index.js
CHANGED
|
@@ -1,26 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./factory"), exports);
|
|
18
|
-
__exportStar(require("./handlers"), exports);
|
|
1
|
+
export * from './factory.js';
|
|
2
|
+
export * from './handlers/index.js';
|
|
19
3
|
/**
|
|
20
4
|
* Default plugins
|
|
21
5
|
*/
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Legacy exports
|
|
25
|
-
*/
|
|
26
|
-
__exportStar(require("./legacy"), exports);
|
|
6
|
+
export * from './plugins/default/index.js';
|
package/dist/logger.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Logger, Options } from './types';
|
|
1
|
+
import { Logger, Options } from './types.js';
|
|
2
2
|
export declare function getLogger(options: Options): Logger;
|
package/dist/logger.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getLogger = getLogger;
|
|
4
1
|
/**
|
|
5
2
|
* Compatibility matrix
|
|
6
3
|
*
|
|
@@ -19,6 +16,6 @@ const noopLogger = {
|
|
|
19
16
|
warn: () => { },
|
|
20
17
|
error: () => { },
|
|
21
18
|
};
|
|
22
|
-
function getLogger(options) {
|
|
19
|
+
export function getLogger(options) {
|
|
23
20
|
return options.logger || noopLogger;
|
|
24
21
|
}
|
package/dist/path-filter.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type
|
|
3
|
-
export declare function matchPathFilter<TReq = http.IncomingMessage>(pathFilter: Filter<TReq> | undefined, uri: string | undefined, req: http.IncomingMessage): boolean;
|
|
1
|
+
import type * as http from 'node:http';
|
|
2
|
+
import type { Filter } from './types.js';
|
|
3
|
+
export declare function matchPathFilter<TReq extends http.IncomingMessage = http.IncomingMessage>(pathFilter: Filter<TReq> | undefined, uri: string | undefined, req: http.IncomingMessage): boolean;
|
package/dist/path-filter.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const micromatch = require("micromatch");
|
|
6
|
-
const url = require("url");
|
|
7
|
-
const errors_1 = require("./errors");
|
|
8
|
-
function matchPathFilter(pathFilter = '/', uri, req) {
|
|
1
|
+
import isGlob from 'is-glob';
|
|
2
|
+
import micromatch from 'micromatch';
|
|
3
|
+
import { ERRORS } from './errors.js';
|
|
4
|
+
export function matchPathFilter(pathFilter = '/', uri, req) {
|
|
9
5
|
// single path
|
|
10
6
|
if (isStringPath(pathFilter)) {
|
|
11
7
|
return matchSingleStringPath(pathFilter, uri);
|
|
@@ -22,14 +18,14 @@ function matchPathFilter(pathFilter = '/', uri, req) {
|
|
|
22
18
|
if (pathFilter.every(isGlobPath)) {
|
|
23
19
|
return matchMultiGlobPath(pathFilter, uri);
|
|
24
20
|
}
|
|
25
|
-
throw new Error(
|
|
21
|
+
throw new Error(ERRORS.ERR_CONTEXT_MATCHER_INVALID_ARRAY);
|
|
26
22
|
}
|
|
27
23
|
// custom matching
|
|
28
24
|
if (typeof pathFilter === 'function') {
|
|
29
25
|
const pathname = getUrlPathName(uri);
|
|
30
26
|
return pathFilter(pathname, req);
|
|
31
27
|
}
|
|
32
|
-
throw new Error(
|
|
28
|
+
throw new Error(ERRORS.ERR_CONTEXT_MATCHER_GENERIC);
|
|
33
29
|
}
|
|
34
30
|
/**
|
|
35
31
|
* @param {String} pathFilter '/api'
|
|
@@ -70,7 +66,7 @@ function matchMultiPath(pathFilterList, uri) {
|
|
|
70
66
|
* @return {String} RFC 3986 path
|
|
71
67
|
*/
|
|
72
68
|
function getUrlPathName(uri) {
|
|
73
|
-
return uri &&
|
|
69
|
+
return uri && new URL(uri, 'http://0.0.0.0').pathname;
|
|
74
70
|
}
|
|
75
71
|
function isStringPath(pathFilter) {
|
|
76
72
|
return typeof pathFilter === 'string' && !isGlob(pathFilter);
|
package/dist/path-rewriter.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const errors_1 = require("./errors");
|
|
6
|
-
const debug_1 = require("./debug");
|
|
7
|
-
const debug = debug_1.Debug.extend('path-rewriter');
|
|
1
|
+
import { isPlainObject } from 'is-plain-object';
|
|
2
|
+
import { Debug } from './debug.js';
|
|
3
|
+
import { ERRORS } from './errors.js';
|
|
4
|
+
const debug = Debug.extend('path-rewriter');
|
|
8
5
|
/**
|
|
9
6
|
* Create rewrite function, to cache parsed rewrite rules.
|
|
10
7
|
*
|
|
11
8
|
* @param {Object} rewriteConfig
|
|
12
9
|
* @return {Function} Function to rewrite paths; This function should accept `path` (request.url) as parameter
|
|
13
10
|
*/
|
|
14
|
-
function createPathRewriter(rewriteConfig) {
|
|
11
|
+
export function createPathRewriter(rewriteConfig) {
|
|
15
12
|
let rulesCache;
|
|
16
13
|
if (!isValidRewriteConfig(rewriteConfig)) {
|
|
17
14
|
return;
|
|
@@ -40,19 +37,19 @@ function isValidRewriteConfig(rewriteConfig) {
|
|
|
40
37
|
if (typeof rewriteConfig === 'function') {
|
|
41
38
|
return true;
|
|
42
39
|
}
|
|
43
|
-
else if (
|
|
40
|
+
else if (isPlainObject(rewriteConfig)) {
|
|
44
41
|
return Object.keys(rewriteConfig).length !== 0;
|
|
45
42
|
}
|
|
46
43
|
else if (rewriteConfig === undefined || rewriteConfig === null) {
|
|
47
44
|
return false;
|
|
48
45
|
}
|
|
49
46
|
else {
|
|
50
|
-
throw new Error(
|
|
47
|
+
throw new Error(ERRORS.ERR_PATH_REWRITER_CONFIG);
|
|
51
48
|
}
|
|
52
49
|
}
|
|
53
50
|
function parsePathRewriteRules(rewriteConfig) {
|
|
54
51
|
const rules = [];
|
|
55
|
-
if (
|
|
52
|
+
if (isPlainObject(rewriteConfig)) {
|
|
56
53
|
for (const [key, value] of Object.entries(rewriteConfig)) {
|
|
57
54
|
rules.push({
|
|
58
55
|
regex: new RegExp(key),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Plugin } from '../../types';
|
|
1
|
+
import { Plugin } from '../../types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Subscribe to {@link https://www.npmjs.com/package/http-proxy#listening-for-proxy-events http-proxy error events} to prevent server from crashing.
|
|
4
4
|
* Errors are logged with {@link https://www.npmjs.com/package/debug debug} library.
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.debugProxyErrorsPlugin = void 0;
|
|
4
|
-
const debug_1 = require("../../debug");
|
|
5
|
-
const debug = debug_1.Debug.extend('debug-proxy-errors-plugin');
|
|
1
|
+
import { Debug } from '../../debug.js';
|
|
2
|
+
const debug = Debug.extend('debug-proxy-errors-plugin');
|
|
6
3
|
/**
|
|
7
4
|
* Subscribe to {@link https://www.npmjs.com/package/http-proxy#listening-for-proxy-events http-proxy error events} to prevent server from crashing.
|
|
8
5
|
* Errors are logged with {@link https://www.npmjs.com/package/debug debug} library.
|
|
9
6
|
*/
|
|
10
|
-
const debugProxyErrorsPlugin = (proxyServer) => {
|
|
7
|
+
export const debugProxyErrorsPlugin = (proxyServer) => {
|
|
11
8
|
/**
|
|
12
9
|
* http-proxy doesn't handle any errors by default (https://github.com/http-party/node-http-proxy#listening-for-proxy-events)
|
|
13
10
|
* Prevent server from crashing when http-proxy errors (uncaught errors)
|
|
@@ -58,4 +55,3 @@ const debugProxyErrorsPlugin = (proxyServer) => {
|
|
|
58
55
|
debug(`http-proxy econnreset event: \n%O`, error);
|
|
59
56
|
});
|
|
60
57
|
};
|
|
61
|
-
exports.debugProxyErrorsPlugin = debugProxyErrorsPlugin;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Plugin } from '../../types';
|
|
1
|
+
import { Plugin } from '../../types.js';
|
|
2
2
|
export declare const errorResponsePlugin: Plugin;
|
|
@@ -1,30 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.errorResponsePlugin = void 0;
|
|
4
|
-
const status_code_1 = require("../../status-code");
|
|
1
|
+
import { getStatusCode } from '../../status-code.js';
|
|
2
|
+
import { sanitize } from '../../utils/sanitize.js';
|
|
5
3
|
function isResponseLike(obj) {
|
|
6
4
|
return obj && typeof obj.writeHead === 'function';
|
|
7
5
|
}
|
|
8
6
|
function isSocketLike(obj) {
|
|
9
7
|
return obj && typeof obj.write === 'function' && !('writeHead' in obj);
|
|
10
8
|
}
|
|
11
|
-
const errorResponsePlugin = (proxyServer, options) => {
|
|
9
|
+
export const errorResponsePlugin = (proxyServer, options) => {
|
|
12
10
|
proxyServer.on('error', (err, req, res, target) => {
|
|
13
11
|
// Re-throw error. Not recoverable since req & res are empty.
|
|
14
|
-
if (!req
|
|
12
|
+
if (!req || !res) {
|
|
15
13
|
throw err; // "Error: Must provide a proper URL as target"
|
|
16
14
|
}
|
|
17
15
|
if (isResponseLike(res)) {
|
|
18
16
|
if (!res.headersSent) {
|
|
19
|
-
const statusCode =
|
|
17
|
+
const statusCode = getStatusCode(err.code);
|
|
20
18
|
res.writeHead(statusCode);
|
|
21
19
|
}
|
|
22
20
|
const host = req.headers && req.headers.host;
|
|
23
|
-
res.end(`Error occurred while trying to proxy: ${host}${req.url}`);
|
|
21
|
+
res.end(`Error occurred while trying to proxy: ${sanitize(host)}${sanitize(req.url)}`);
|
|
24
22
|
}
|
|
25
23
|
else if (isSocketLike(res)) {
|
|
26
24
|
res.destroy();
|
|
27
25
|
}
|
|
28
26
|
});
|
|
29
27
|
};
|
|
30
|
-
exports.errorResponsePlugin = errorResponsePlugin;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from './debug-proxy-errors-plugin';
|
|
2
|
-
export * from './error-response-plugin';
|
|
3
|
-
export * from './logger-plugin';
|
|
4
|
-
export * from './proxy-events';
|
|
1
|
+
export * from './debug-proxy-errors-plugin.js';
|
|
2
|
+
export * from './error-response-plugin.js';
|
|
3
|
+
export * from './logger-plugin.js';
|
|
4
|
+
export * from './proxy-events.js';
|
|
@@ -1,20 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./debug-proxy-errors-plugin"), exports);
|
|
18
|
-
__exportStar(require("./error-response-plugin"), exports);
|
|
19
|
-
__exportStar(require("./logger-plugin"), exports);
|
|
20
|
-
__exportStar(require("./proxy-events"), exports);
|
|
1
|
+
export * from './debug-proxy-errors-plugin.js';
|
|
2
|
+
export * from './error-response-plugin.js';
|
|
3
|
+
export * from './logger-plugin.js';
|
|
4
|
+
export * from './proxy-events.js';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Plugin } from '../../types';
|
|
1
|
+
import { Plugin } from '../../types.js';
|
|
2
2
|
export declare const loggerPlugin: Plugin;
|