@rspack/dev-server 2.0.3 → 2.2.0
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/client/modules/logger/createConsoleLogger.d.ts +1 -1
- package/client/modules/logger/index.d.ts +4 -2
- package/client/overlay.d.ts +1 -1
- package/client/overlay.js +2 -1
- package/client/utils/ansiHTML.d.ts +1 -1
- package/client/utils/ansiHTML.js +1 -1
- package/dist/0~chokidar.js +45 -46
- package/dist/0~connect-history-api-fallback.js +2 -2
- package/dist/0~connect-next.js +43 -39
- package/dist/0~debug.js +10 -10
- package/dist/0~http-proxy-middleware.js +136 -69
- package/dist/0~launch-editor.js +111 -63
- package/dist/0~serve-static.js +9 -9
- package/dist/{465.js → 619.js} +116 -123
- package/dist/index.js +1 -1
- package/package.json +18 -19
package/dist/0~debug.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { __webpack_require__ } from "./
|
|
2
|
-
import "./
|
|
1
|
+
import { __webpack_require__ } from "./619.js";
|
|
2
|
+
import "./619.js";
|
|
3
3
|
__webpack_require__.add({
|
|
4
|
-
"./node_modules/.pnpm/debug@4.4.
|
|
4
|
+
"./node_modules/.pnpm/debug@4.4.3_supports-color@8.1.1/node_modules/debug/src/browser.js" (module, exports, __webpack_require__) {
|
|
5
5
|
exports.formatArgs = formatArgs;
|
|
6
6
|
exports.save = save;
|
|
7
7
|
exports.load = load;
|
|
@@ -134,7 +134,7 @@ __webpack_require__.add({
|
|
|
134
134
|
return localStorage;
|
|
135
135
|
} catch (error) {}
|
|
136
136
|
}
|
|
137
|
-
module.exports = __webpack_require__("./node_modules/.pnpm/debug@4.4.
|
|
137
|
+
module.exports = __webpack_require__("./node_modules/.pnpm/debug@4.4.3_supports-color@8.1.1/node_modules/debug/src/common.js")(exports);
|
|
138
138
|
const { formatters } = module.exports;
|
|
139
139
|
formatters.j = function(v) {
|
|
140
140
|
try {
|
|
@@ -144,7 +144,7 @@ __webpack_require__.add({
|
|
|
144
144
|
}
|
|
145
145
|
};
|
|
146
146
|
},
|
|
147
|
-
"./node_modules/.pnpm/debug@4.4.
|
|
147
|
+
"./node_modules/.pnpm/debug@4.4.3_supports-color@8.1.1/node_modules/debug/src/common.js" (module, __unused_rspack_exports, __webpack_require__) {
|
|
148
148
|
function setup(env) {
|
|
149
149
|
createDebug.debug = createDebug;
|
|
150
150
|
createDebug.default = createDebug;
|
|
@@ -286,11 +286,11 @@ __webpack_require__.add({
|
|
|
286
286
|
}
|
|
287
287
|
module.exports = setup;
|
|
288
288
|
},
|
|
289
|
-
"./node_modules/.pnpm/debug@4.4.
|
|
290
|
-
if ("u" < typeof process || 'renderer' === process.type || true === process.browser || process.__nwjs) module.exports = __webpack_require__("./node_modules/.pnpm/debug@4.4.
|
|
291
|
-
else module.exports = __webpack_require__("./node_modules/.pnpm/debug@4.4.
|
|
289
|
+
"./node_modules/.pnpm/debug@4.4.3_supports-color@8.1.1/node_modules/debug/src/index.js" (module, __unused_rspack_exports, __webpack_require__) {
|
|
290
|
+
if ("u" < typeof process || 'renderer' === process.type || true === process.browser || process.__nwjs) module.exports = __webpack_require__("./node_modules/.pnpm/debug@4.4.3_supports-color@8.1.1/node_modules/debug/src/browser.js");
|
|
291
|
+
else module.exports = __webpack_require__("./node_modules/.pnpm/debug@4.4.3_supports-color@8.1.1/node_modules/debug/src/node.js");
|
|
292
292
|
},
|
|
293
|
-
"./node_modules/.pnpm/debug@4.4.
|
|
293
|
+
"./node_modules/.pnpm/debug@4.4.3_supports-color@8.1.1/node_modules/debug/src/node.js" (module, exports, __webpack_require__) {
|
|
294
294
|
const tty = __webpack_require__("tty");
|
|
295
295
|
const util = __webpack_require__("util");
|
|
296
296
|
exports.init = init;
|
|
@@ -428,7 +428,7 @@ __webpack_require__.add({
|
|
|
428
428
|
const keys = Object.keys(exports.inspectOpts);
|
|
429
429
|
for(let i = 0; i < keys.length; i++)debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
|
|
430
430
|
}
|
|
431
|
-
module.exports = __webpack_require__("./node_modules/.pnpm/debug@4.4.
|
|
431
|
+
module.exports = __webpack_require__("./node_modules/.pnpm/debug@4.4.3_supports-color@8.1.1/node_modules/debug/src/common.js")(exports);
|
|
432
432
|
const { formatters } = module.exports;
|
|
433
433
|
formatters.o = function(v) {
|
|
434
434
|
this.inspectOpts.colors = this.useColors;
|
|
@@ -5,13 +5,14 @@ import node_http2 from "node:http2";
|
|
|
5
5
|
import { EventEmitter } from "node:events";
|
|
6
6
|
import "node:net";
|
|
7
7
|
import "node:stream";
|
|
8
|
+
import { styleText } from "node:util";
|
|
8
9
|
import { URL as external_node_url_URL } from "node:url";
|
|
9
10
|
import { URL as external_url_URL } from "url";
|
|
10
11
|
import "node:zlib";
|
|
11
12
|
import "node:querystring";
|
|
12
|
-
import { __webpack_require__ } from "./
|
|
13
|
+
import { __webpack_require__ } from "./619.js";
|
|
13
14
|
import "./0~debug.js";
|
|
14
|
-
import "./
|
|
15
|
+
import "./619.js";
|
|
15
16
|
__webpack_require__.add({
|
|
16
17
|
"./node_modules/.pnpm/braces@3.0.3/node_modules/braces/index.js" (module, __unused_rspack_exports, __webpack_require__) {
|
|
17
18
|
const stringify = __webpack_require__("./node_modules/.pnpm/braces@3.0.3/node_modules/braces/lib/stringify.js");
|
|
@@ -2796,6 +2797,7 @@ __webpack_require__.add({
|
|
|
2796
2797
|
}
|
|
2797
2798
|
});
|
|
2798
2799
|
const upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i;
|
|
2800
|
+
const transferEncodingConnectionToken = /(^|,)\s*transfer-encoding\s*($|,)/i;
|
|
2799
2801
|
const defaultAgents = {
|
|
2800
2802
|
http: new node_http.Agent({
|
|
2801
2803
|
keepAlive: true,
|
|
@@ -2809,6 +2811,16 @@ const defaultAgents = {
|
|
|
2809
2811
|
})
|
|
2810
2812
|
};
|
|
2811
2813
|
const isSSL = /^https|wss/;
|
|
2814
|
+
function forceConnectionCloseForTransferEncoding(headers) {
|
|
2815
|
+
let carriesTransferEncoding = false;
|
|
2816
|
+
for(const key in headers)if (void 0 !== headers[key] && "transfer-encoding" === key.toLowerCase()) {
|
|
2817
|
+
carriesTransferEncoding = true;
|
|
2818
|
+
break;
|
|
2819
|
+
}
|
|
2820
|
+
const connection = headers.connection;
|
|
2821
|
+
const connectionMarksTransferEncoding = "string" == typeof connection && transferEncodingConnectionToken.test(connection);
|
|
2822
|
+
if (carriesTransferEncoding || connectionMarksTransferEncoding) headers.connection = "close";
|
|
2823
|
+
}
|
|
2812
2824
|
const HTTP2_HEADER_BLACKLIST = [
|
|
2813
2825
|
":method",
|
|
2814
2826
|
":path",
|
|
@@ -2832,6 +2844,10 @@ function setupOutgoing(outgoing, options, req, forward) {
|
|
|
2832
2844
|
const value = options[forward || "target"][e];
|
|
2833
2845
|
if (void 0 !== value) outgoing[e] = value;
|
|
2834
2846
|
}
|
|
2847
|
+
if (void 0 === outgoing.host && "string" == typeof outgoing.hostname) {
|
|
2848
|
+
const bracketedHost = outgoing.hostname.includes(":") && !outgoing.hostname.startsWith("[") ? `[${outgoing.hostname}]` : outgoing.hostname;
|
|
2849
|
+
outgoing.host = outgoing.port ? `${bracketedHost}:${outgoing.port}` : bracketedHost;
|
|
2850
|
+
}
|
|
2835
2851
|
outgoing.method = options.method || req.method;
|
|
2836
2852
|
outgoing.headers = {
|
|
2837
2853
|
...req.headers
|
|
@@ -2853,6 +2869,8 @@ function setupOutgoing(outgoing, options, req, forward) {
|
|
|
2853
2869
|
outgoing.headers = outgoing.headers || {};
|
|
2854
2870
|
if ("string" != typeof outgoing.headers.connection || !upgradeHeader.test(outgoing.headers.connection)) outgoing.headers.connection = "close";
|
|
2855
2871
|
}
|
|
2872
|
+
outgoing.headers = outgoing.headers || {};
|
|
2873
|
+
forceConnectionCloseForTransferEncoding(outgoing.headers);
|
|
2856
2874
|
const target = options[forward || "target"];
|
|
2857
2875
|
const targetPath = target && false !== options.prependPath ? target.pathname || "" : "";
|
|
2858
2876
|
const targetSearch = target instanceof URL && false !== options.prependPath ? target.search || "" : "";
|
|
@@ -2950,6 +2968,7 @@ const webOutgoingMiddleware = [
|
|
|
2950
2968
|
defineProxyOutgoingMiddleware((req, res, proxyRes, options)=>{
|
|
2951
2969
|
if ((options.hostRewrite || options.autoRewrite || options.protocolRewrite) && proxyRes.headers.location && redirectRegex.test(String(proxyRes.statusCode))) {
|
|
2952
2970
|
const target = _toURL(options.target);
|
|
2971
|
+
const keepProtocolRelative = proxyRes.headers.location.startsWith("//") && !options.protocolRewrite;
|
|
2953
2972
|
const u = new URL(proxyRes.headers.location, target);
|
|
2954
2973
|
if (target.host !== u.host) return;
|
|
2955
2974
|
if (options.hostRewrite) u.host = options.hostRewrite;
|
|
@@ -2958,7 +2977,7 @@ const webOutgoingMiddleware = [
|
|
|
2958
2977
|
else if (req.headers.host) u.host = req.headers.host;
|
|
2959
2978
|
}
|
|
2960
2979
|
if (options.protocolRewrite) u.protocol = options.protocolRewrite;
|
|
2961
|
-
proxyRes.headers.location = u.
|
|
2980
|
+
proxyRes.headers.location = keepProtocolRelative ? u.href.slice(u.protocol.length) : u.href;
|
|
2962
2981
|
}
|
|
2963
2982
|
}),
|
|
2964
2983
|
defineProxyOutgoingMiddleware((req, res, proxyRes, options)=>{
|
|
@@ -3008,7 +3027,7 @@ const nativeAgents = {
|
|
|
3008
3027
|
http: node_http,
|
|
3009
3028
|
https: node_https
|
|
3010
3029
|
};
|
|
3011
|
-
const redirectStatuses = new Set([
|
|
3030
|
+
const redirectStatuses = /* @__PURE__ */ new Set([
|
|
3012
3031
|
301,
|
|
3013
3032
|
302,
|
|
3014
3033
|
303,
|
|
@@ -3017,10 +3036,7 @@ const redirectStatuses = new Set([
|
|
|
3017
3036
|
]);
|
|
3018
3037
|
const webIncomingMiddleware = [
|
|
3019
3038
|
defineProxyMiddleware((req)=>{
|
|
3020
|
-
if (("DELETE" === req.method || "OPTIONS" === req.method) && !req.headers["content-length"])
|
|
3021
|
-
req.headers["content-length"] = "0";
|
|
3022
|
-
delete req.headers["transfer-encoding"];
|
|
3023
|
-
}
|
|
3039
|
+
if (("DELETE" === req.method || "OPTIONS" === req.method) && !req.headers["content-length"] && !req.headers["transfer-encoding"]) req.headers["content-length"] = "0";
|
|
3024
3040
|
}),
|
|
3025
3041
|
defineProxyMiddleware((req, res, options)=>{
|
|
3026
3042
|
if (options.timeout) req.socket.setTimeout(options.timeout, ()=>{
|
|
@@ -3123,6 +3139,7 @@ const webIncomingMiddleware = [
|
|
|
3123
3139
|
delete redirectHeaders["content-type"];
|
|
3124
3140
|
delete redirectHeaders["transfer-encoding"];
|
|
3125
3141
|
}
|
|
3142
|
+
forceConnectionCloseForTransferEncoding(redirectHeaders);
|
|
3126
3143
|
const redirectOpts = {
|
|
3127
3144
|
hostname: location.hostname,
|
|
3128
3145
|
port: location.port || (isHTTPS ? 443 : 80),
|
|
@@ -3349,15 +3366,15 @@ function _createProxyFn(type, server) {
|
|
|
3349
3366
|
for (const pass of server._getPasses(type)){
|
|
3350
3367
|
let stop;
|
|
3351
3368
|
try {
|
|
3352
|
-
stop = pass(req, res, requestOptions, server, head, (error)=>{
|
|
3369
|
+
stop = pass(req, res, requestOptions, server, head, (error, _req, _res, url)=>{
|
|
3353
3370
|
if (server.listenerCount("error") > 0) {
|
|
3354
|
-
server.emit("error", error, req, res);
|
|
3371
|
+
server.emit("error", error, req, res, url);
|
|
3355
3372
|
_resolve();
|
|
3356
3373
|
} else _reject(error);
|
|
3357
3374
|
});
|
|
3358
3375
|
} catch (error) {
|
|
3359
3376
|
if (server.listenerCount("error") > 0) {
|
|
3360
|
-
server.emit("error", error, req, res);
|
|
3377
|
+
server.emit("error", error, req, res, requestOptions.target || requestOptions.forward);
|
|
3361
3378
|
_resolve();
|
|
3362
3379
|
} else _reject(error);
|
|
3363
3380
|
break;
|
|
@@ -3370,29 +3387,41 @@ function _createProxyFn(type, server) {
|
|
|
3370
3387
|
return callbackPromise;
|
|
3371
3388
|
};
|
|
3372
3389
|
}
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
ERRORS["ERR_CONFIG_FACTORY_TARGET_MISSING"] = "[HPM] Missing \"target\" option. Example: {target: \"http://www.example.org\"}";
|
|
3383
|
-
ERRORS["ERR_CONTEXT_MATCHER_GENERIC"] = "[HPM] Invalid pathFilter. Expecting something like: \"/api\" or [\"/api\", \"/ajax\"]";
|
|
3384
|
-
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\"].";
|
|
3385
|
-
ERRORS["ERR_PATH_REWRITER_CONFIG"] = "[HPM] Invalid pathRewrite config. Expecting object with pathRewrite config or a rewrite function";
|
|
3386
|
-
})(errors_ERRORS || (errors_ERRORS = {}));
|
|
3390
|
+
class errors_HttpProxyMiddlewareError extends Error {
|
|
3391
|
+
code;
|
|
3392
|
+
constructor(message, code){
|
|
3393
|
+
super(message);
|
|
3394
|
+
this.code = code;
|
|
3395
|
+
this.name = this.constructor.name;
|
|
3396
|
+
if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor);
|
|
3397
|
+
}
|
|
3398
|
+
}
|
|
3387
3399
|
function verifyConfig(options) {
|
|
3388
|
-
if (!options.target && !options.router) throw new
|
|
3400
|
+
if (!options.target && !options.router) throw new errors_HttpProxyMiddlewareError('[HPM] Missing "target" option. Example: {target: "http://www.example.org"}', 'ERR_CONFIG_FACTORY_TARGET_MISSING');
|
|
3389
3401
|
}
|
|
3390
|
-
const src = __webpack_require__("./node_modules/.pnpm/debug@4.4.
|
|
3402
|
+
const src = __webpack_require__("./node_modules/.pnpm/debug@4.4.3_supports-color@8.1.1/node_modules/debug/src/index.js");
|
|
3391
3403
|
const Debug = src('http-proxy-middleware');
|
|
3404
|
+
function definePlugin(fn) {
|
|
3405
|
+
return fn;
|
|
3406
|
+
}
|
|
3392
3407
|
const debug = Debug.extend('debug-proxy-errors-plugin');
|
|
3393
|
-
const
|
|
3408
|
+
const BODY_PARSER_ERROR_MESSAGE = `[HPM] Connection reset (ECONNRESET) detected with non-empty "req.body" [ERR_HPM.GH40].
|
|
3409
|
+
|
|
3410
|
+
This usually means that the POST request body (req.body) was already parsed before reaching the proxy.
|
|
3411
|
+
When bodyParser runs first, it consumes the request stream, leaving the proxy unable to forward the body data to the target server.
|
|
3412
|
+
|
|
3413
|
+
How to fix this issue:
|
|
3414
|
+
- Option 1: Place the proxy middleware before the bodyParser middleware.
|
|
3415
|
+
- Option 2: Use 'fixRequestBody()' helper to fix this issue.
|
|
3416
|
+
|
|
3417
|
+
For more details, see: https://github.com/chimurai/http-proxy-middleware/issues/40\n`;
|
|
3418
|
+
function hasParsedBody(req) {
|
|
3419
|
+
return Boolean(req && 'POST' === req.method && 'body' in req && req.body);
|
|
3420
|
+
}
|
|
3421
|
+
const debugProxyErrorsPlugin = definePlugin((proxyServer, options)=>{
|
|
3394
3422
|
proxyServer.on('error', (error, req, res, target)=>{
|
|
3395
3423
|
debug(`httpxy error event: \n%O`, error);
|
|
3424
|
+
if ('ECONNRESET' === error.code && hasParsedBody(req)) console.error(styleText('red', BODY_PARSER_ERROR_MESSAGE));
|
|
3396
3425
|
});
|
|
3397
3426
|
proxyServer.on('proxyReq', (proxyReq, req, socket)=>{
|
|
3398
3427
|
socket.on('error', (error)=>{
|
|
@@ -3425,11 +3454,18 @@ const debugProxyErrorsPlugin = (proxyServer)=>{
|
|
|
3425
3454
|
proxyServer.on('econnreset', (error, req, res, target)=>{
|
|
3426
3455
|
debug(`httpxy econnreset event: \n%O`, error);
|
|
3427
3456
|
});
|
|
3428
|
-
};
|
|
3457
|
+
});
|
|
3429
3458
|
function getStatusCode(errorCode) {
|
|
3430
3459
|
let statusCode;
|
|
3431
|
-
if (/HPE_INVALID/.test(errorCode))
|
|
3432
|
-
|
|
3460
|
+
if (/HPE_INVALID/.test(errorCode)) {
|
|
3461
|
+
statusCode = 502;
|
|
3462
|
+
return statusCode;
|
|
3463
|
+
}
|
|
3464
|
+
if (/HPM_ERR_INVALID_MULTIPART_/.test(errorCode)) {
|
|
3465
|
+
statusCode = 400;
|
|
3466
|
+
return statusCode;
|
|
3467
|
+
}
|
|
3468
|
+
switch(errorCode){
|
|
3433
3469
|
case 'ECONNRESET':
|
|
3434
3470
|
case 'ENOTFOUND':
|
|
3435
3471
|
case 'ECONNREFUSED':
|
|
@@ -3451,7 +3487,7 @@ function isResponseLike(obj) {
|
|
|
3451
3487
|
function isSocketLike(obj) {
|
|
3452
3488
|
return obj && 'function' == typeof obj.write && !('writeHead' in obj);
|
|
3453
3489
|
}
|
|
3454
|
-
const errorResponsePlugin = (proxyServer, options)=>{
|
|
3490
|
+
const errorResponsePlugin = definePlugin((proxyServer, options)=>{
|
|
3455
3491
|
proxyServer.on('error', (err, req, res, target)=>{
|
|
3456
3492
|
if (!req || !res) throw err;
|
|
3457
3493
|
if (isResponseLike(res)) {
|
|
@@ -3463,7 +3499,7 @@ const errorResponsePlugin = (proxyServer, options)=>{
|
|
|
3463
3499
|
res.end(`Error occurred while trying to proxy: ${sanitize(host)}${sanitize(req.url)}`);
|
|
3464
3500
|
} else if (isSocketLike(res)) res.destroy();
|
|
3465
3501
|
});
|
|
3466
|
-
};
|
|
3502
|
+
});
|
|
3467
3503
|
const noopLogger = {
|
|
3468
3504
|
info: ()=>{},
|
|
3469
3505
|
warn: ()=>{},
|
|
@@ -3483,7 +3519,7 @@ function createUrl({ protocol, host, port, path }) {
|
|
|
3483
3519
|
function logger_plugin_getPort(sockets) {
|
|
3484
3520
|
return Object.keys(sockets || {})?.[0]?.split(':')[1];
|
|
3485
3521
|
}
|
|
3486
|
-
const loggerPlugin = (proxyServer, options)=>{
|
|
3522
|
+
const loggerPlugin = definePlugin((proxyServer, options)=>{
|
|
3487
3523
|
const logger = getLogger(options);
|
|
3488
3524
|
proxyServer.on('error', (err, req, res, target)=>{
|
|
3489
3525
|
const hostname = req?.headers?.host;
|
|
@@ -3520,12 +3556,12 @@ const loggerPlugin = (proxyServer, options)=>{
|
|
|
3520
3556
|
proxyServer.on('close', (req, proxySocket, proxyHead)=>{
|
|
3521
3557
|
logger.info('[HPM] Client disconnected: %o', proxySocket.address());
|
|
3522
3558
|
});
|
|
3523
|
-
};
|
|
3559
|
+
});
|
|
3524
3560
|
function function_getFunctionName(fn) {
|
|
3525
3561
|
return fn.name || '[anonymous Function]';
|
|
3526
3562
|
}
|
|
3527
3563
|
const proxy_events_debug = Debug.extend('proxy-events-plugin');
|
|
3528
|
-
const proxyEventsPlugin = (proxyServer, options)=>{
|
|
3564
|
+
const proxyEventsPlugin = definePlugin((proxyServer, options)=>{
|
|
3529
3565
|
if (!options.on) return;
|
|
3530
3566
|
let eventName;
|
|
3531
3567
|
for(eventName in options.on)if (Object.prototype.hasOwnProperty.call(options.on, eventName)) {
|
|
@@ -3534,7 +3570,7 @@ const proxyEventsPlugin = (proxyServer, options)=>{
|
|
|
3534
3570
|
proxy_events_debug(`register event handler: "${eventName}" -> "${function_getFunctionName(handler)}"`);
|
|
3535
3571
|
proxyServer.on(eventName, handler);
|
|
3536
3572
|
}
|
|
3537
|
-
};
|
|
3573
|
+
});
|
|
3538
3574
|
function getPlugins(options) {
|
|
3539
3575
|
const maybeErrorResponsePlugin = options.on?.error ? [] : [
|
|
3540
3576
|
errorResponsePlugin
|
|
@@ -3559,13 +3595,13 @@ function matchPathFilter(pathFilter = '/', uri, req) {
|
|
|
3559
3595
|
if (Array.isArray(pathFilter)) {
|
|
3560
3596
|
if (pathFilter.every(isStringPath)) return matchMultiPath(pathFilter, uri);
|
|
3561
3597
|
if (pathFilter.every(isGlobPath)) return matchMultiGlobPath(pathFilter, uri);
|
|
3562
|
-
throw new
|
|
3598
|
+
throw new errors_HttpProxyMiddlewareError('[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"].', 'HPM_INVALID_PATH_FILTER_ARRAY_CONFIG');
|
|
3563
3599
|
}
|
|
3564
3600
|
if ('function' == typeof pathFilter) {
|
|
3565
3601
|
const pathname = getUrlPathName(uri);
|
|
3566
|
-
return pathFilter(pathname, req);
|
|
3602
|
+
return Boolean(pathFilter(pathname, req));
|
|
3567
3603
|
}
|
|
3568
|
-
throw new
|
|
3604
|
+
throw new errors_HttpProxyMiddlewareError('[HPM] Invalid pathFilter. Expecting something like: "/api" or ["/api", "/ajax"]', 'HPM_INVALID_PATH_FILTER_CONFIG');
|
|
3569
3605
|
}
|
|
3570
3606
|
function matchSingleStringPath(pathFilter, uri) {
|
|
3571
3607
|
const pathname = getUrlPathName(uri);
|
|
@@ -3627,7 +3663,7 @@ function isValidRewriteConfig(rewriteConfig) {
|
|
|
3627
3663
|
if ('function' == typeof rewriteConfig) return true;
|
|
3628
3664
|
if (isPlainObject(rewriteConfig)) return 0 !== Object.keys(rewriteConfig).length;
|
|
3629
3665
|
if (null == rewriteConfig) return false;
|
|
3630
|
-
throw new
|
|
3666
|
+
throw new errors_HttpProxyMiddlewareError('[HPM] Invalid pathRewrite config. Expecting object with pathRewrite config or a rewrite function', 'HPM_INVALID_PATH_REWRITER_CONFIG');
|
|
3631
3667
|
}
|
|
3632
3668
|
function parsePathRewriteRules(rewriteConfig) {
|
|
3633
3669
|
const rules = [];
|
|
@@ -3641,20 +3677,26 @@ function parsePathRewriteRules(rewriteConfig) {
|
|
|
3641
3677
|
return rules;
|
|
3642
3678
|
}
|
|
3643
3679
|
const router_debug = Debug.extend('router');
|
|
3644
|
-
async function getTarget(req, config) {
|
|
3680
|
+
async function getTarget(req, res, config) {
|
|
3645
3681
|
let newTarget;
|
|
3646
3682
|
const router = config.router;
|
|
3647
3683
|
if (isPlainObject(router)) newTarget = getTargetFromProxyTable(req, router);
|
|
3648
|
-
else if ('function' == typeof router) newTarget = await router(req);
|
|
3684
|
+
else if ('function' == typeof router) newTarget = await router(req, res, config);
|
|
3649
3685
|
return newTarget;
|
|
3650
3686
|
}
|
|
3651
3687
|
function getTargetFromProxyTable(req, table) {
|
|
3652
3688
|
let result;
|
|
3653
3689
|
const host = req.headers.host ?? '';
|
|
3654
3690
|
const path = req.url ?? '';
|
|
3655
|
-
const hostAndPath = host + path;
|
|
3656
3691
|
for (const [key, value] of Object.entries(table))if (containsPath(key)) {
|
|
3657
|
-
if (
|
|
3692
|
+
if (isHostAndPathKey(key)) {
|
|
3693
|
+
const [keyHost, keyPath] = splitHostAndPathKey(key);
|
|
3694
|
+
if (host === keyHost && path.startsWith(keyPath)) {
|
|
3695
|
+
result = value;
|
|
3696
|
+
router_debug('match: "%s" -> "%s"', key, result);
|
|
3697
|
+
break;
|
|
3698
|
+
}
|
|
3699
|
+
} else if (path.startsWith(key)) {
|
|
3658
3700
|
result = value;
|
|
3659
3701
|
router_debug('match: "%s" -> "%s"', key, result);
|
|
3660
3702
|
break;
|
|
@@ -3669,6 +3711,16 @@ function getTargetFromProxyTable(req, table) {
|
|
|
3669
3711
|
function containsPath(v) {
|
|
3670
3712
|
return v.indexOf('/') > -1;
|
|
3671
3713
|
}
|
|
3714
|
+
function isHostAndPathKey(v) {
|
|
3715
|
+
return containsPath(v) && !v.startsWith('/');
|
|
3716
|
+
}
|
|
3717
|
+
function splitHostAndPathKey(v) {
|
|
3718
|
+
const firstSlash = v.indexOf('/');
|
|
3719
|
+
return [
|
|
3720
|
+
v.slice(0, firstSlash),
|
|
3721
|
+
v.slice(firstSlash)
|
|
3722
|
+
];
|
|
3723
|
+
}
|
|
3672
3724
|
const ipv6_debug = Debug.extend('ipv6');
|
|
3673
3725
|
function normalizeIPv6LiteralTargets(options) {
|
|
3674
3726
|
options.target = normalizeIPv6ProxyTarget(options.target, 'target');
|
|
@@ -3677,9 +3729,12 @@ function normalizeIPv6LiteralTargets(options) {
|
|
|
3677
3729
|
function normalizeIPv6ProxyTarget(target, optionName) {
|
|
3678
3730
|
const targetUrl = toTargetUrl(target);
|
|
3679
3731
|
if (targetUrl && isBracketedIPv6Hostname(targetUrl.hostname)) {
|
|
3732
|
+
const normalizedHostname = normalizeIPv6DestinationHostname(stripBrackets(targetUrl.hostname));
|
|
3680
3733
|
ipv6_debug('normalized IPv6 "%s" %s', optionName, target);
|
|
3734
|
+
const auth = targetUrl.username || targetUrl.password ? `${targetUrl.username}:${targetUrl.password}` : void 0;
|
|
3681
3735
|
return {
|
|
3682
|
-
hostname:
|
|
3736
|
+
hostname: normalizedHostname,
|
|
3737
|
+
auth,
|
|
3683
3738
|
pathname: targetUrl.pathname,
|
|
3684
3739
|
port: targetUrl.port,
|
|
3685
3740
|
protocol: targetUrl.protocol,
|
|
@@ -3698,9 +3753,16 @@ function isBracketedIPv6Hostname(hostname) {
|
|
|
3698
3753
|
function stripBrackets(hostname) {
|
|
3699
3754
|
return hostname.replace(/^\[|\]$/g, '');
|
|
3700
3755
|
}
|
|
3756
|
+
function normalizeIPv6DestinationHostname(hostname) {
|
|
3757
|
+
if ('::' === hostname) {
|
|
3758
|
+
ipv6_debug('normalizing hostname unspecified IPv6 address (::) to loopback (::1)');
|
|
3759
|
+
return '::1';
|
|
3760
|
+
}
|
|
3761
|
+
return hostname;
|
|
3762
|
+
}
|
|
3701
3763
|
class HttpProxyMiddleware {
|
|
3702
|
-
|
|
3703
|
-
|
|
3764
|
+
wsInternalSubscribedServers = new WeakSet();
|
|
3765
|
+
activeServers = new Set();
|
|
3704
3766
|
proxyOptions;
|
|
3705
3767
|
proxy;
|
|
3706
3768
|
pathRewriter;
|
|
@@ -3714,14 +3776,18 @@ class HttpProxyMiddleware {
|
|
|
3714
3776
|
this.registerPlugins(this.proxy, this.proxyOptions);
|
|
3715
3777
|
this.pathRewriter = createPathRewriter(this.proxyOptions.pathRewrite);
|
|
3716
3778
|
this.middleware.upgrade = (req, socket, head)=>{
|
|
3717
|
-
|
|
3779
|
+
const server = this.#getServer(req);
|
|
3780
|
+
if (server && !this.wsInternalSubscribedServers.has(server)) this.handleUpgrade(req, socket, head);
|
|
3718
3781
|
};
|
|
3719
3782
|
}
|
|
3783
|
+
#getServer(req) {
|
|
3784
|
+
return req.socket?.server;
|
|
3785
|
+
}
|
|
3720
3786
|
middleware = async (req, res, next)=>{
|
|
3721
3787
|
if (this.shouldProxy(this.proxyOptions.pathFilter, req)) {
|
|
3722
3788
|
let activeProxyOptions;
|
|
3723
3789
|
try {
|
|
3724
|
-
activeProxyOptions = await this.prepareProxyRequest(req);
|
|
3790
|
+
activeProxyOptions = await this.prepareProxyRequest(req, res);
|
|
3725
3791
|
if (!activeProxyOptions.target && !activeProxyOptions.forward) throw new Error('Must provide a proper URL as target');
|
|
3726
3792
|
} catch (err) {
|
|
3727
3793
|
next?.(err);
|
|
@@ -3735,15 +3801,17 @@ class HttpProxyMiddleware {
|
|
|
3735
3801
|
next?.(err);
|
|
3736
3802
|
}
|
|
3737
3803
|
} else next?.();
|
|
3738
|
-
const server = req
|
|
3739
|
-
if (server && !this.
|
|
3804
|
+
const server = this.#getServer(req);
|
|
3805
|
+
if (server && !this.activeServers.has(server)) {
|
|
3806
|
+
Debug('registering server close listener');
|
|
3807
|
+
this.activeServers.add(server);
|
|
3740
3808
|
server.on('close', ()=>{
|
|
3741
|
-
Debug('server close signal received
|
|
3742
|
-
this.
|
|
3743
|
-
|
|
3744
|
-
|
|
3809
|
+
Debug('server close signal received.');
|
|
3810
|
+
this.activeServers.delete(server);
|
|
3811
|
+
if (this.activeServers.size > 0) return void Debug(`proxy server not closed: ${this.activeServers.size} server(s) still active`);
|
|
3812
|
+
Debug('closing proxy server');
|
|
3813
|
+
this.proxy.close(()=>Debug('proxy server closed'));
|
|
3745
3814
|
});
|
|
3746
|
-
this.serverOnCloseSubscribed = true;
|
|
3747
3815
|
}
|
|
3748
3816
|
if (true === this.proxyOptions.ws && server) this.catchUpgradeRequest(server);
|
|
3749
3817
|
};
|
|
@@ -3755,18 +3823,17 @@ class HttpProxyMiddleware {
|
|
|
3755
3823
|
});
|
|
3756
3824
|
}
|
|
3757
3825
|
catchUpgradeRequest = (server)=>{
|
|
3758
|
-
if (!this.
|
|
3826
|
+
if (!this.wsInternalSubscribedServers.has(server)) {
|
|
3759
3827
|
Debug('subscribing to server upgrade event');
|
|
3760
3828
|
server.on('upgrade', this.handleUpgrade);
|
|
3761
|
-
this.
|
|
3829
|
+
this.wsInternalSubscribedServers.add(server);
|
|
3762
3830
|
}
|
|
3763
3831
|
};
|
|
3764
3832
|
handleUpgrade = async (req, socket, head)=>{
|
|
3765
3833
|
try {
|
|
3766
3834
|
if (this.shouldProxy(this.proxyOptions.pathFilter, req)) {
|
|
3767
|
-
const
|
|
3768
|
-
|
|
3769
|
-
await this.proxy.ws(proxiedReq, socket, activeProxyOptions, head);
|
|
3835
|
+
const activeProxyOptions = await this.prepareProxyRequest(req, void 0);
|
|
3836
|
+
await this.proxy.ws(req, socket, activeProxyOptions, head);
|
|
3770
3837
|
Debug('server upgrade event received. Proxying WebSocket');
|
|
3771
3838
|
}
|
|
3772
3839
|
} catch (err) {
|
|
@@ -3782,26 +3849,26 @@ class HttpProxyMiddleware {
|
|
|
3782
3849
|
return false;
|
|
3783
3850
|
}
|
|
3784
3851
|
};
|
|
3785
|
-
prepareProxyRequest = async (req)=>{
|
|
3852
|
+
prepareProxyRequest = async (req, res)=>{
|
|
3786
3853
|
const newProxyOptions = Object.assign({}, this.proxyOptions);
|
|
3787
|
-
await this.applyRouter(req, newProxyOptions);
|
|
3854
|
+
await this.applyRouter(req, res, newProxyOptions);
|
|
3788
3855
|
normalizeIPv6LiteralTargets(newProxyOptions);
|
|
3789
|
-
await this.applyPathRewrite(req, this.pathRewriter);
|
|
3856
|
+
await this.applyPathRewrite(req, res, this.pathRewriter, newProxyOptions);
|
|
3790
3857
|
return newProxyOptions;
|
|
3791
3858
|
};
|
|
3792
|
-
applyRouter = async (req, options)=>{
|
|
3859
|
+
applyRouter = async (req, res, options)=>{
|
|
3793
3860
|
let newTarget;
|
|
3794
3861
|
if (options.router) {
|
|
3795
|
-
newTarget = await getTarget(req, options);
|
|
3862
|
+
newTarget = await getTarget(req, res, options);
|
|
3796
3863
|
if (newTarget) {
|
|
3797
3864
|
Debug('router new target: "%s"', newTarget);
|
|
3798
3865
|
options.target = newTarget;
|
|
3799
3866
|
}
|
|
3800
3867
|
}
|
|
3801
3868
|
};
|
|
3802
|
-
applyPathRewrite = async (req, pathRewriter)=>{
|
|
3869
|
+
applyPathRewrite = async (req, res, pathRewriter, options)=>{
|
|
3803
3870
|
if (req.url && pathRewriter) {
|
|
3804
|
-
const path = await pathRewriter(req.url, req);
|
|
3871
|
+
const path = await pathRewriter(req.url, req, res, options);
|
|
3805
3872
|
if ('string' == typeof path) {
|
|
3806
3873
|
Debug('pathRewrite new path: %s', path);
|
|
3807
3874
|
req.url = path;
|