nitro 3.0.1-alpha.2 → 3.0.260415-beta
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/LICENSE +6 -0
- package/README.md +2 -2
- package/dist/THIRD-PARTY-LICENSES.md +1646 -0
- package/dist/_build/common.mjs +7261 -3812
- package/dist/_build/rolldown.mjs +32 -42
- package/dist/_build/rollup.mjs +28 -48
- package/dist/_build/vite.build.mjs +10 -10
- package/dist/_chunks/nitro.mjs +102 -327
- package/dist/_chunks/nitro2.mjs +8 -9
- package/dist/_chunks/nitro3.mjs +136 -0
- package/dist/_chunks/nitro4.mjs +127 -0
- package/dist/_chunks/utils.mjs +40 -29
- package/dist/_common.mjs +13 -25
- package/dist/_dev.d.mts +0 -3
- package/dist/{_chunks/dev.mjs → _dev.mjs} +132 -330
- package/dist/_libs/_.mjs +2 -0
- package/dist/_libs/_2.mjs +2 -0
- package/dist/_libs/_3.mjs +2 -0
- package/dist/_libs/_4.mjs +2 -0
- package/dist/_libs/_5.mjs +2 -0
- package/dist/_libs/_6.mjs +2 -0
- package/dist/_libs/_7.mjs +2 -0
- package/dist/_libs/c12+rc9.mjs +814 -0
- package/dist/_libs/{c12+giget+readdirp+chokidar.d.mts → c12+readdirp+chokidar.d.mts} +49 -40
- package/dist/_libs/citty.mjs +142 -41
- package/dist/_libs/commondir+is-reference.mjs +60 -56
- package/dist/_libs/compatx.d.mts +0 -2
- package/dist/_libs/compatx.mjs +1 -4
- package/dist/_libs/esbuild.d.mts +0 -1
- package/dist/_libs/escape-string-regexp.mjs +1 -4
- package/dist/_libs/{pluginutils+plugin-commonjs.d.mts → estree+pluginutils.d.mts} +0 -5
- package/dist/_libs/estree-walker.mjs +4 -92
- package/dist/_libs/exsolve.d.mts +1 -0
- package/dist/_libs/hasown+resolve+deepmerge.mjs +160 -246
- package/dist/_libs/httpxy.d.mts +20 -13
- package/dist/_libs/httpxy.mjs +519 -95
- package/dist/_libs/js-tokens.d.mts +1 -0
- package/dist/_libs/klona.mjs +1 -4
- package/dist/_libs/magic-string.d.mts +0 -2
- package/dist/_libs/mlly.d.mts +0 -2
- package/dist/_libs/nypm+tinyexec.mjs +822 -0
- package/dist/_libs/perfect-debounce.mjs +68 -0
- package/dist/_libs/pkg-types.d.mts +0 -3
- package/dist/_libs/plugin-alias.mjs +1 -5
- package/dist/_libs/plugin-inject.mjs +1 -7
- package/dist/_libs/plugin-json.mjs +1 -5
- package/dist/_libs/pluginutils.mjs +3 -35
- package/dist/_libs/readdirp+chokidar.mjs +187 -365
- package/dist/_libs/remapping.mjs +1 -5
- package/dist/_libs/resolve-uri+gen-mapping.mjs +15 -53
- package/dist/_libs/rou3.d.mts +1 -4
- package/dist/_libs/rou3.mjs +223 -78
- package/dist/_libs/std-env.d.mts +8 -2
- package/dist/_libs/strip-literal.d.mts +1 -0
- package/dist/_libs/tsconfck.mjs +21 -334
- package/dist/_libs/ultrahtml.mjs +3 -16
- package/dist/_libs/unimport+unplugin.mjs +244 -388
- package/dist/_libs/unplugin+unimport.d.mts +5 -15
- package/dist/_libs/unwasm.d.mts +0 -3
- package/dist/_presets.mjs +576 -488
- package/dist/builder.d.mts +5 -25
- package/dist/builder.mjs +3 -8
- package/dist/cli/_chunks/build.mjs +22 -25
- package/dist/cli/_chunks/common.mjs +1 -4
- package/dist/cli/_chunks/deploy.mjs +37 -0
- package/dist/cli/_chunks/dev.mjs +6 -11
- package/dist/cli/_chunks/docs.mjs +28 -0
- package/dist/cli/_chunks/list.mjs +4 -8
- package/dist/cli/_chunks/prepare.mjs +2 -6
- package/dist/cli/_chunks/preview.mjs +48 -0
- package/dist/cli/_chunks/run.mjs +7 -11
- package/dist/cli/_chunks/task.mjs +1 -5
- package/dist/cli/index.mjs +5 -6
- package/dist/docs/0.docs/0.index/index.md +56 -0
- package/dist/docs/0.docs/1.quick-start.md +110 -0
- package/dist/docs/0.docs/10.lifecycle.md +204 -0
- package/dist/docs/0.docs/11.openapi.md +291 -0
- package/dist/docs/0.docs/12.plugins.md +164 -0
- package/dist/docs/0.docs/13.tasks.md +277 -0
- package/dist/docs/0.docs/14.websocket.md +386 -0
- package/dist/docs/0.docs/15.migration.md +213 -0
- package/dist/docs/0.docs/16.nightly.md +31 -0
- package/dist/docs/0.docs/2.renderer.md +322 -0
- package/dist/docs/0.docs/3.routing.md +711 -0
- package/dist/docs/0.docs/4.server-entry.md +239 -0
- package/dist/docs/0.docs/5.cache.md +408 -0
- package/dist/docs/0.docs/6.storage.md +261 -0
- package/dist/docs/0.docs/7.assets.md +166 -0
- package/dist/docs/0.docs/8.configuration.md +256 -0
- package/dist/docs/0.docs/9.database.md +185 -0
- package/dist/docs/1.deploy/0.index/index.md +64 -0
- package/dist/docs/1.deploy/1.runtimes/0.node.md +63 -0
- package/dist/docs/1.deploy/1.runtimes/1.bun.md +15 -0
- package/dist/docs/1.deploy/1.runtimes/2.deno.md +19 -0
- package/dist/docs/1.deploy/2.providers/0.alwaysdata.md +50 -0
- package/dist/docs/1.deploy/2.providers/1.aws.md +47 -0
- package/dist/docs/1.deploy/2.providers/10.flightcontrol.md +67 -0
- package/dist/docs/1.deploy/2.providers/11.genezio.md +67 -0
- package/dist/docs/1.deploy/2.providers/12.github-pages.md +68 -0
- package/dist/docs/1.deploy/2.providers/13.gitlab-pages.md +37 -0
- package/dist/docs/1.deploy/2.providers/14.heroku.md +84 -0
- package/dist/docs/1.deploy/2.providers/15.iis.md +38 -0
- package/dist/docs/1.deploy/2.providers/16.koyeb.md +109 -0
- package/dist/docs/1.deploy/2.providers/17.netlify.md +47 -0
- package/dist/docs/1.deploy/2.providers/18.platform-sh.md +37 -0
- package/dist/docs/1.deploy/2.providers/19.render.md +37 -0
- package/dist/docs/1.deploy/2.providers/2.aws-amplify.md +81 -0
- package/dist/docs/1.deploy/2.providers/20.stormkit.md +24 -0
- package/dist/docs/1.deploy/2.providers/21.vercel.md +270 -0
- package/dist/docs/1.deploy/2.providers/22.zeabur.md +19 -0
- package/dist/docs/1.deploy/2.providers/23.zephyr.md +99 -0
- package/dist/docs/1.deploy/2.providers/24.zerops.md +102 -0
- package/dist/docs/1.deploy/2.providers/3.azure.md +72 -0
- package/dist/docs/1.deploy/2.providers/4.cleavr.md +33 -0
- package/dist/docs/1.deploy/2.providers/5.cloudflare.md +369 -0
- package/dist/docs/1.deploy/2.providers/6.deno-deploy.md +66 -0
- package/dist/docs/1.deploy/2.providers/7.digitalocean.md +46 -0
- package/dist/docs/1.deploy/2.providers/8.edgeone.md +20 -0
- package/dist/docs/1.deploy/2.providers/9.firebase.md +32 -0
- package/dist/docs/2.config/0.index/index.md +1221 -0
- package/dist/docs/3.examples/0.index/index.md +3 -0
- package/dist/docs/3.examples/1.api-routes.md +145 -0
- package/dist/docs/3.examples/10.hono.md +74 -0
- package/dist/docs/3.examples/11.import-alias.md +97 -0
- package/dist/docs/3.examples/12.middleware.md +91 -0
- package/dist/docs/3.examples/13.mono-jsx.md +68 -0
- package/dist/docs/3.examples/14.nano-jsx.md +70 -0
- package/dist/docs/3.examples/15.plugins.md +91 -0
- package/dist/docs/3.examples/16.renderer.md +113 -0
- package/dist/docs/3.examples/17.runtime-config.md +97 -0
- package/dist/docs/3.examples/18.server-fetch.md +87 -0
- package/dist/docs/3.examples/19.shiki.md +198 -0
- package/dist/docs/3.examples/2.auto-imports.md +92 -0
- package/dist/docs/3.examples/20.virtual-routes.md +74 -0
- package/dist/docs/3.examples/21.vite-nitro-plugin.md +79 -0
- package/dist/docs/3.examples/22.vite-rsc.md +1041 -0
- package/dist/docs/3.examples/23.vite-ssr-html.md +217 -0
- package/dist/docs/3.examples/24.vite-ssr-preact.md +247 -0
- package/dist/docs/3.examples/25.vite-ssr-react.md +226 -0
- package/dist/docs/3.examples/26.vite-ssr-solid.md +256 -0
- package/dist/docs/3.examples/27.vite-ssr-tsr-react.md +442 -0
- package/dist/docs/3.examples/28.vite-ssr-tss-react.md +444 -0
- package/dist/docs/3.examples/29.vite-ssr-vue-router.md +617 -0
- package/dist/docs/3.examples/3.cached-handler.md +81 -0
- package/dist/docs/3.examples/30.vite-trpc.md +335 -0
- package/dist/docs/3.examples/31.websocket.md +282 -0
- package/dist/docs/3.examples/4.custom-error-handler.md +98 -0
- package/dist/docs/3.examples/5.database.md +157 -0
- package/dist/docs/3.examples/6.elysia.md +70 -0
- package/dist/docs/3.examples/7.express.md +78 -0
- package/dist/docs/3.examples/8.fastify.md +79 -0
- package/dist/docs/3.examples/9.hello-world.md +68 -0
- package/dist/docs/README.md +86 -0
- package/dist/docs/index.md +121 -0
- package/dist/node_modules/@poppinss/dumper/build/formatters/html/main.js +8 -0
- package/dist/node_modules/@poppinss/dumper/package.json +1 -1
- package/dist/node_modules/@speed-highlight/core/dist/index.js +4 -4
- package/dist/node_modules/@speed-highlight/core/dist/terminal.js +2 -2
- package/dist/node_modules/@speed-highlight/core/package.json +1 -1
- package/dist/node_modules/cookie-es/dist/index.mjs +299 -250
- package/dist/node_modules/cookie-es/package.json +26 -23
- package/dist/node_modules/croner/dist/croner.js +1 -1
- package/dist/node_modules/croner/package.json +11 -1
- package/dist/node_modules/defu/dist/defu.mjs +2 -2
- package/dist/node_modules/defu/package.json +33 -28
- package/dist/node_modules/rendu/dist/_chunks/libs/cookie-es.mjs +151 -0
- package/dist/node_modules/rendu/dist/index.mjs +5 -112
- package/dist/node_modules/rendu/package.json +25 -24
- package/dist/node_modules/youch/build/helpers-B9BQYaS6.js +23 -0
- package/dist/node_modules/youch/build/index.js +204 -351
- package/dist/node_modules/youch/build/public/error_info/script.js +1 -1
- package/dist/node_modules/youch/build/public_dir-C5bujZKB.js +25 -0
- package/dist/node_modules/youch/build/src/templates/error_cause/main.js +44 -0
- package/dist/node_modules/youch/build/src/templates/error_info/main.js +72 -0
- package/dist/node_modules/youch/build/src/templates/error_metadata/main.js +65 -0
- package/dist/node_modules/youch/build/src/templates/error_stack/main.js +152 -0
- package/dist/node_modules/youch/build/src/templates/error_stack_source/main.js +46 -0
- package/dist/node_modules/youch/build/src/templates/header/main.js +24 -0
- package/dist/node_modules/youch/build/src/templates/layout/main.js +27 -0
- package/dist/node_modules/youch/package.json +35 -32
- package/dist/presets/_nitro/runtime/nitro-dev.mjs +12 -57
- package/dist/presets/_nitro/runtime/nitro-prerenderer.mjs +1 -0
- package/dist/presets/_nitro/runtime/service-worker.mjs +1 -2
- package/dist/presets/aws-lambda/runtime/_utils.mjs +6 -6
- package/dist/presets/aws-lambda/runtime/aws-lambda-streaming.mjs +3 -1
- package/dist/presets/azure/runtime/_utils.mjs +5 -5
- package/dist/presets/azure/runtime/azure-swa.mjs +5 -5
- package/dist/presets/bun/runtime/bun.mjs +9 -6
- package/dist/presets/cloudflare/runtime/_module-handler.mjs +1 -1
- package/dist/presets/cloudflare/runtime/cloudflare-durable.mjs +4 -4
- package/dist/presets/cloudflare/runtime/cloudflare-module.mjs +3 -3
- package/dist/presets/cloudflare/runtime/cloudflare-pages.mjs +2 -2
- package/dist/presets/cloudflare/runtime/plugin.dev.mjs +10 -21
- package/dist/presets/deno/runtime/deno-deploy.mjs +4 -4
- package/dist/presets/deno/runtime/deno-server.mjs +9 -6
- package/dist/presets/edgeone/runtime/edgeone.mjs +10 -0
- package/dist/presets/netlify/runtime/netlify-edge.mjs +2 -3
- package/dist/presets/netlify/runtime/netlify.mjs +1 -1
- package/dist/presets/node/runtime/node-cluster.mjs +5 -4
- package/dist/presets/node/runtime/node-middleware.mjs +1 -1
- package/dist/presets/node/runtime/node-server.mjs +8 -5
- package/dist/presets/stormkit/runtime/stormkit.mjs +1 -2
- package/dist/presets/vercel/runtime/cron-handler.mjs +25 -0
- package/dist/presets/vercel/runtime/queue-handler.mjs +21 -0
- package/dist/presets/vercel/runtime/vercel.node.mjs +3 -3
- package/dist/presets/vercel/runtime/vercel.web.mjs +3 -5
- package/dist/presets/winterjs/runtime/winterjs.mjs +10 -10
- package/dist/presets/zephyr/runtime/server.mjs +3 -0
- package/dist/runtime/internal/app.mjs +12 -11
- package/dist/runtime/internal/cache.d.mts +0 -4
- package/dist/runtime/internal/cache.mjs +32 -256
- package/dist/runtime/internal/context.d.mts +3 -1
- package/dist/runtime/internal/context.mjs +1 -9
- package/dist/runtime/internal/error/dev.d.mts +5 -4
- package/dist/runtime/internal/error/dev.mjs +47 -49
- package/dist/runtime/internal/error/hooks.d.mts +1 -1
- package/dist/runtime/internal/error/prod.d.mts +2 -5
- package/dist/runtime/internal/error/prod.mjs +19 -33
- package/dist/runtime/internal/error/utils.d.mts +4 -4
- package/dist/runtime/internal/meta.d.mts +1 -1
- package/dist/runtime/internal/plugin.d.mts +2 -2
- package/dist/runtime/internal/route-rules.d.mts +11 -4
- package/dist/runtime/internal/route-rules.mjs +15 -5
- package/dist/runtime/internal/routes/dev-tasks.d.mts +3 -2
- package/dist/runtime/internal/routes/dev-tasks.mjs +15 -10
- package/dist/runtime/internal/routes/openapi.mjs +2 -2
- package/dist/runtime/internal/routes/renderer-template.d.mts +1 -1
- package/dist/runtime/internal/routes/renderer-template.dev.d.mts +2 -1
- package/dist/runtime/internal/routes/scalar.mjs +3 -3
- package/dist/runtime/internal/routes/swagger.mjs +7 -4
- package/dist/runtime/internal/runtime-config.d.mts +1 -1
- package/dist/runtime/internal/runtime-config.mjs +2 -2
- package/dist/runtime/internal/static.mjs +5 -4
- package/dist/runtime/internal/task.d.mts +3 -1
- package/dist/runtime/internal/task.mjs +7 -7
- package/dist/runtime/internal/vite/dev-entry.mjs +6 -3
- package/dist/runtime/internal/vite/dev-worker.mjs +264 -0
- package/dist/runtime/meta.d.mts +1 -0
- package/dist/runtime/meta.mjs +2 -0
- package/dist/runtime/nitro.d.mts +2 -0
- package/dist/runtime/nitro.mjs +4 -2
- package/dist/runtime/virtual/error-handler.mjs +1 -1
- package/dist/runtime/virtual/renderer-template.mjs +1 -1
- package/dist/runtime/virtual/server-assets.d.mts +2 -1
- package/dist/runtime/virtual/tracing.d.mts +5 -0
- package/dist/runtime/virtual/tracing.mjs +1 -0
- package/dist/runtime/vite.d.mts +1 -1
- package/dist/types/index.d.mts +215 -195
- package/dist/types/index.mjs +1 -11
- package/dist/vite.d.mts +3 -8
- package/dist/vite.mjs +285 -253
- package/lib/tsconfig.json +3 -5
- package/package.json +97 -80
- package/dist/_libs/confbox.mjs +0 -2509
- package/dist/_libs/nypm+giget+tinyexec.mjs +0 -3603
- package/dist/_libs/rc9+c12+dotenv.mjs +0 -972
- package/dist/node_modules/hookable/dist/index.mjs +0 -266
- package/dist/node_modules/hookable/package.json +0 -52
- package/dist/node_modules/youch/build/chunk-4L7RY2JA.js +0 -42
- package/dist/node_modules/youch/build/chunk-7QV3D5YX.js +0 -83
- package/dist/node_modules/youch/build/chunk-AUGPHE32.js +0 -39
- package/dist/node_modules/youch/build/chunk-CM7DWJNZ.js +0 -44
- package/dist/node_modules/youch/build/chunk-EJH674NB.js +0 -223
- package/dist/node_modules/youch/build/chunk-OIJ3WD7L.js +0 -81
- package/dist/node_modules/youch/build/chunk-P36L72PL.js +0 -87
- package/dist/node_modules/youch/build/chunk-PE3GG3TN.js +0 -65
- package/dist/node_modules/youch/build/chunk-X53OIOJH.js +0 -70
- package/dist/presets/_nitro/runtime/nitro-dev.d.mts +0 -2
- package/dist/presets/_nitro/runtime/nitro-prerenderer.d.mts +0 -3
- package/dist/presets/_nitro/runtime/service-worker.d.mts +0 -2
- package/dist/presets/aws-amplify/runtime/aws-amplify.d.mts +0 -2
- package/dist/presets/aws-lambda/runtime/_utils.d.mts +0 -8
- package/dist/presets/aws-lambda/runtime/aws-lambda-streaming.d.mts +0 -2
- package/dist/presets/aws-lambda/runtime/aws-lambda.d.mts +0 -3
- package/dist/presets/azure/runtime/_utils.d.mts +0 -2
- package/dist/presets/azure/runtime/azure-swa.d.mts +0 -5
- package/dist/presets/bun/runtime/bun.d.mts +0 -3
- package/dist/presets/cloudflare/runtime/_module-handler.d.mts +0 -16
- package/dist/presets/cloudflare/runtime/cloudflare-durable.d.mts +0 -11
- package/dist/presets/cloudflare/runtime/cloudflare-module.d.mts +0 -3
- package/dist/presets/cloudflare/runtime/cloudflare-pages.d.mts +0 -20
- package/dist/presets/cloudflare/runtime/plugin.dev.d.mts +0 -3
- package/dist/presets/deno/runtime/deno-deploy.d.mts +0 -5
- package/dist/presets/deno/runtime/deno-server.d.mts +0 -3
- package/dist/presets/netlify/runtime/netlify-edge.d.mts +0 -3
- package/dist/presets/netlify/runtime/netlify.d.mts +0 -4
- package/dist/presets/node/runtime/node-cluster.d.mts +0 -3
- package/dist/presets/node/runtime/node-middleware.d.mts +0 -3
- package/dist/presets/node/runtime/node-server.d.mts +0 -3
- package/dist/presets/standard/runtime/server.d.mts +0 -3
- package/dist/presets/stormkit/runtime/stormkit.d.mts +0 -21
- package/dist/presets/vercel/runtime/isr.d.mts +0 -2
- package/dist/presets/vercel/runtime/vercel.node.d.mts +0 -3
- package/dist/presets/vercel/runtime/vercel.web.d.mts +0 -8
- package/dist/presets/winterjs/runtime/winterjs.d.mts +0 -2
- package/dist/presets/zeabur/runtime/zeabur.d.mts +0 -3
- package/dist/runtime/internal/vite/node-runner.mjs +0 -359
package/dist/_libs/httpxy.mjs
CHANGED
|
@@ -1,17 +1,30 @@
|
|
|
1
|
-
import { n as __exportAll } from "../_common.mjs";
|
|
2
|
-
import http from "node:http";
|
|
3
|
-
import https from "node:https";
|
|
4
1
|
import { EventEmitter } from "node:events";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
createProxyServer: () => createProxyServer
|
|
10
|
-
});
|
|
2
|
+
import { Readable } from "node:stream";
|
|
3
|
+
import http, { request } from "node:http";
|
|
4
|
+
import https, { request as request$1 } from "node:https";
|
|
5
|
+
import http2 from "node:http2";
|
|
11
6
|
const upgradeHeader = /(^|,)\s*upgrade\s*($|,)/i;
|
|
7
|
+
const defaultAgents = {
|
|
8
|
+
http: new http.Agent({
|
|
9
|
+
keepAlive: true,
|
|
10
|
+
maxSockets: 256,
|
|
11
|
+
maxFreeSockets: 64
|
|
12
|
+
}),
|
|
13
|
+
https: new https.Agent({
|
|
14
|
+
keepAlive: true,
|
|
15
|
+
maxSockets: 256,
|
|
16
|
+
maxFreeSockets: 64
|
|
17
|
+
})
|
|
18
|
+
};
|
|
12
19
|
const isSSL = /^https|wss/;
|
|
20
|
+
const HTTP2_HEADER_BLACKLIST = [
|
|
21
|
+
":method",
|
|
22
|
+
":path",
|
|
23
|
+
":scheme",
|
|
24
|
+
":authority"
|
|
25
|
+
];
|
|
13
26
|
function setupOutgoing(outgoing, options, req, forward) {
|
|
14
|
-
outgoing.port = options[forward || "target"].port || (isSSL.test(options[forward || "target"].protocol) ? 443 : 80);
|
|
27
|
+
outgoing.port = options[forward || "target"].port || (isSSL.test(options[forward || "target"].protocol ?? "http") ? 443 : 80);
|
|
15
28
|
for (const e of [
|
|
16
29
|
"host",
|
|
17
30
|
"hostname",
|
|
@@ -23,29 +36,43 @@ function setupOutgoing(outgoing, options, req, forward) {
|
|
|
23
36
|
"ca",
|
|
24
37
|
"ciphers",
|
|
25
38
|
"secureProtocol"
|
|
26
|
-
])
|
|
39
|
+
]) {
|
|
40
|
+
const value = options[forward || "target"][e];
|
|
41
|
+
if (value !== void 0) outgoing[e] = value;
|
|
42
|
+
}
|
|
27
43
|
outgoing.method = options.method || req.method;
|
|
28
44
|
outgoing.headers = { ...req.headers };
|
|
29
|
-
if (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
};
|
|
45
|
+
if (req.headers?.[":authority"]) outgoing.headers.host = req.headers[":authority"];
|
|
46
|
+
if (options.headers) for (const key of Object.keys(options.headers)) outgoing.headers[key] = options.headers[key];
|
|
47
|
+
if (req.httpVersionMajor > 1) for (const header of HTTP2_HEADER_BLACKLIST) delete outgoing.headers[header];
|
|
33
48
|
if (options.auth) outgoing.auth = options.auth;
|
|
34
49
|
if (options.ca) outgoing.ca = options.ca;
|
|
35
|
-
if (isSSL.test(options[forward || "target"].protocol)) outgoing.rejectUnauthorized = options.secure === void 0 ? true : options.secure;
|
|
36
|
-
outgoing.agent = options.agent || false;
|
|
50
|
+
if (isSSL.test(options[forward || "target"].protocol ?? "http")) outgoing.rejectUnauthorized = options.secure === void 0 ? true : options.secure;
|
|
51
|
+
if (options.agent !== void 0) outgoing.agent = options.agent || false;
|
|
52
|
+
else if (req.httpVersionMajor > 1) outgoing.agent = false;
|
|
53
|
+
else {
|
|
54
|
+
const targetProto = options[forward || "target"].protocol ?? "http";
|
|
55
|
+
outgoing.agent = isSSL.test(targetProto) ? defaultAgents.https : defaultAgents.http;
|
|
56
|
+
}
|
|
37
57
|
outgoing.localAddress = options.localAddress;
|
|
38
58
|
if (!outgoing.agent) {
|
|
39
59
|
outgoing.headers = outgoing.headers || {};
|
|
40
60
|
if (typeof outgoing.headers.connection !== "string" || !upgradeHeader.test(outgoing.headers.connection)) outgoing.headers.connection = "close";
|
|
41
61
|
}
|
|
42
62
|
const target = options[forward || "target"];
|
|
43
|
-
const targetPath = target && options.prependPath !== false ? target.pathname ||
|
|
44
|
-
const
|
|
45
|
-
|
|
63
|
+
const targetPath = target && options.prependPath !== false ? target.pathname || "" : "";
|
|
64
|
+
const targetSearch = target instanceof URL && options.prependPath !== false ? target.search || "" : "";
|
|
65
|
+
const reqUrl = req.url || "";
|
|
66
|
+
const qIdx = reqUrl.indexOf("?");
|
|
67
|
+
const reqPath = qIdx === -1 ? reqUrl : reqUrl.slice(0, qIdx);
|
|
68
|
+
const reqSearch = qIdx === -1 ? "" : reqUrl.slice(qIdx);
|
|
69
|
+
const normalizedPath = reqPath ? reqPath[0] === "/" ? reqPath : "/" + reqPath : "/";
|
|
70
|
+
let outgoingPath = options.toProxy ? "/" + reqUrl : normalizedPath + reqSearch;
|
|
46
71
|
outgoingPath = options.ignorePath ? "" : outgoingPath;
|
|
47
|
-
|
|
48
|
-
if (
|
|
72
|
+
let fullPath = joinURL(targetPath, outgoingPath);
|
|
73
|
+
if (targetSearch) fullPath = fullPath.includes("?") ? fullPath.replace("?", targetSearch + "&") : fullPath + targetSearch;
|
|
74
|
+
outgoing.path = fullPath;
|
|
75
|
+
if (options.changeOrigin) outgoing.headers.host = requiresPort(outgoing.port, options[forward || "target"].protocol) && !hasPort(outgoing.host) ? outgoing.host + ":" + outgoing.port : outgoing.host ?? void 0;
|
|
49
76
|
return outgoing;
|
|
50
77
|
}
|
|
51
78
|
function joinURL(base, path) {
|
|
@@ -64,12 +91,14 @@ function setupSocket(socket) {
|
|
|
64
91
|
return socket;
|
|
65
92
|
}
|
|
66
93
|
function getPort(req) {
|
|
67
|
-
const
|
|
94
|
+
const hostHeader = req.headers[":authority"] || req.headers.host;
|
|
95
|
+
const res = hostHeader ? hostHeader.match(/:(\d+)/) : "";
|
|
68
96
|
if (res) return res[1];
|
|
69
97
|
return hasEncryptedConnection(req) ? "443" : "80";
|
|
70
98
|
}
|
|
71
99
|
function hasEncryptedConnection(req) {
|
|
72
|
-
|
|
100
|
+
const socket = req.socket;
|
|
101
|
+
return !!socket && "encrypted" in socket && socket.encrypted;
|
|
73
102
|
}
|
|
74
103
|
function rewriteCookieProperty(header, config, property) {
|
|
75
104
|
if (Array.isArray(header)) return header.map(function(headerElement) {
|
|
@@ -83,11 +112,23 @@ function rewriteCookieProperty(header, config, property) {
|
|
|
83
112
|
return newValue ? prefix + newValue : "";
|
|
84
113
|
});
|
|
85
114
|
}
|
|
115
|
+
function parseAddr(addr) {
|
|
116
|
+
if (typeof addr === "string") {
|
|
117
|
+
if (addr.startsWith("unix:")) return { socketPath: addr.slice(5) };
|
|
118
|
+
const url = new URL(addr);
|
|
119
|
+
return {
|
|
120
|
+
host: url.hostname,
|
|
121
|
+
port: Number(url.port) || (isSSL.test(url.protocol) ? 443 : 80)
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
if (!addr.socketPath && !addr.port) throw new Error("ProxyAddr must have either `port` or `socketPath`");
|
|
125
|
+
return addr;
|
|
126
|
+
}
|
|
86
127
|
function hasPort(host) {
|
|
87
|
-
return !!~host.indexOf(":");
|
|
128
|
+
return host ? !!~host.indexOf(":") : false;
|
|
88
129
|
}
|
|
89
130
|
function requiresPort(_port, _protocol) {
|
|
90
|
-
const protocol = _protocol
|
|
131
|
+
const protocol = _protocol?.split(":")[0];
|
|
91
132
|
const port = +_port;
|
|
92
133
|
if (!port) return false;
|
|
93
134
|
switch (protocol) {
|
|
@@ -107,39 +148,43 @@ function defineProxyMiddleware(m) {
|
|
|
107
148
|
function defineProxyOutgoingMiddleware(m) {
|
|
108
149
|
return m;
|
|
109
150
|
}
|
|
110
|
-
const redirectRegex = /^201|30([
|
|
151
|
+
const redirectRegex = /^201|30([12378])$/;
|
|
111
152
|
const webOutgoingMiddleware = [
|
|
112
153
|
defineProxyOutgoingMiddleware((req, res, proxyRes) => {
|
|
113
|
-
if (req.httpVersion === "1.0") delete proxyRes.headers["transfer-encoding"];
|
|
154
|
+
if (req.httpVersion === "1.0" || req.httpVersionMajor >= 2 || proxyRes.statusCode === 204 || proxyRes.statusCode === 304) delete proxyRes.headers["transfer-encoding"];
|
|
114
155
|
}),
|
|
115
156
|
defineProxyOutgoingMiddleware((req, res, proxyRes) => {
|
|
116
157
|
if (req.httpVersion === "1.0") proxyRes.headers.connection = req.headers.connection || "close";
|
|
117
|
-
else if (req.
|
|
158
|
+
else if (req.httpVersionMajor < 2 && !proxyRes.headers.connection) proxyRes.headers.connection = req.headers.connection || "keep-alive";
|
|
159
|
+
else if (req.httpVersionMajor >= 2) delete proxyRes.headers.connection;
|
|
118
160
|
}),
|
|
119
161
|
defineProxyOutgoingMiddleware((req, res, proxyRes, options) => {
|
|
120
162
|
if ((options.hostRewrite || options.autoRewrite || options.protocolRewrite) && proxyRes.headers.location && redirectRegex.test(String(proxyRes.statusCode))) {
|
|
121
|
-
const target =
|
|
122
|
-
const u = new URL(proxyRes.headers.location);
|
|
163
|
+
const target = _toURL(options.target);
|
|
164
|
+
const u = new URL(proxyRes.headers.location, target);
|
|
123
165
|
if (target.host !== u.host) return;
|
|
124
166
|
if (options.hostRewrite) u.host = options.hostRewrite;
|
|
125
|
-
else if (options.autoRewrite)
|
|
167
|
+
else if (options.autoRewrite) {
|
|
168
|
+
if (req.headers[":authority"]) u.host = req.headers[":authority"];
|
|
169
|
+
else if (req.headers.host) u.host = req.headers.host;
|
|
170
|
+
}
|
|
126
171
|
if (options.protocolRewrite) u.protocol = options.protocolRewrite;
|
|
127
172
|
proxyRes.headers.location = u.toString();
|
|
128
173
|
}
|
|
129
174
|
}),
|
|
130
175
|
defineProxyOutgoingMiddleware((req, res, proxyRes, options) => {
|
|
131
|
-
|
|
132
|
-
|
|
176
|
+
const rewriteCookieDomainConfig = typeof options.cookieDomainRewrite === "string" ? { "*": options.cookieDomainRewrite } : options.cookieDomainRewrite;
|
|
177
|
+
const rewriteCookiePathConfig = typeof options.cookiePathRewrite === "string" ? { "*": options.cookiePathRewrite } : options.cookiePathRewrite;
|
|
133
178
|
const preserveHeaderKeyCase = options.preserveHeaderKeyCase;
|
|
134
179
|
let rawHeaderKeyMap;
|
|
135
180
|
const setHeader = function(key, header) {
|
|
136
|
-
if (header === void 0) return;
|
|
181
|
+
if (header === void 0 || !String(key).trim()) return;
|
|
137
182
|
if (rewriteCookieDomainConfig && key.toLowerCase() === "set-cookie") header = rewriteCookieProperty(header, rewriteCookieDomainConfig, "domain");
|
|
138
183
|
if (rewriteCookiePathConfig && key.toLowerCase() === "set-cookie") header = rewriteCookieProperty(header, rewriteCookiePathConfig, "path");
|
|
139
|
-
|
|
184
|
+
try {
|
|
185
|
+
res.setHeader(String(key).trim(), header);
|
|
186
|
+
} catch {}
|
|
140
187
|
};
|
|
141
|
-
if (typeof rewriteCookieDomainConfig === "string") rewriteCookieDomainConfig = { "*": rewriteCookieDomainConfig };
|
|
142
|
-
if (typeof rewriteCookiePathConfig === "string") rewriteCookiePathConfig = { "*": rewriteCookiePathConfig };
|
|
143
188
|
if (preserveHeaderKeyCase && proxyRes.rawHeaders !== void 0) {
|
|
144
189
|
rawHeaderKeyMap = {};
|
|
145
190
|
for (let i = 0; i < proxyRes.rawHeaders.length; i += 2) {
|
|
@@ -154,16 +199,29 @@ const webOutgoingMiddleware = [
|
|
|
154
199
|
}
|
|
155
200
|
}),
|
|
156
201
|
defineProxyOutgoingMiddleware((req, res, proxyRes) => {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
res.statusMessage = proxyRes.statusMessage;
|
|
160
|
-
} else res.statusCode = proxyRes.statusCode;
|
|
202
|
+
res.statusCode = proxyRes.statusCode;
|
|
203
|
+
if (proxyRes.statusMessage && req.httpVersionMajor < 2) res.statusMessage = proxyRes.statusMessage;
|
|
161
204
|
})
|
|
162
205
|
];
|
|
206
|
+
function _toURL(target) {
|
|
207
|
+
if (target instanceof URL) return target;
|
|
208
|
+
if (typeof target === "string") return new URL(target);
|
|
209
|
+
const protocol = target.protocol || "http:";
|
|
210
|
+
const host = target.host || target.hostname || "localhost";
|
|
211
|
+
const port = target.port;
|
|
212
|
+
return new URL(`${protocol}//${host}${port ? ":" + port : ""}`);
|
|
213
|
+
}
|
|
163
214
|
const nativeAgents = {
|
|
164
215
|
http,
|
|
165
216
|
https
|
|
166
217
|
};
|
|
218
|
+
const redirectStatuses = new Set([
|
|
219
|
+
301,
|
|
220
|
+
302,
|
|
221
|
+
303,
|
|
222
|
+
307,
|
|
223
|
+
308
|
|
224
|
+
]);
|
|
167
225
|
const webIncomingMiddleware = [
|
|
168
226
|
defineProxyMiddleware((req) => {
|
|
169
227
|
if ((req.method === "DELETE" || req.method === "OPTIONS") && !req.headers["content-length"]) {
|
|
@@ -172,7 +230,9 @@ const webIncomingMiddleware = [
|
|
|
172
230
|
}
|
|
173
231
|
}),
|
|
174
232
|
defineProxyMiddleware((req, res, options) => {
|
|
175
|
-
if (options.timeout) req.socket.setTimeout(options.timeout)
|
|
233
|
+
if (options.timeout) req.socket.setTimeout(options.timeout, () => {
|
|
234
|
+
req.socket.destroy();
|
|
235
|
+
});
|
|
176
236
|
}),
|
|
177
237
|
defineProxyMiddleware((req, res, options) => {
|
|
178
238
|
if (!options.xfwd) return;
|
|
@@ -186,16 +246,19 @@ const webIncomingMiddleware = [
|
|
|
186
246
|
"for",
|
|
187
247
|
"port",
|
|
188
248
|
"proto"
|
|
189
|
-
])
|
|
190
|
-
|
|
249
|
+
]) {
|
|
250
|
+
const key = "x-forwarded-" + header;
|
|
251
|
+
if (!req.headers[key]) req.headers[key] = values[header];
|
|
252
|
+
}
|
|
253
|
+
req.headers["x-forwarded-host"] = req.headers["x-forwarded-host"] || req.headers[":authority"] || req.headers.host || "";
|
|
191
254
|
}),
|
|
192
255
|
defineProxyMiddleware((req, res, options, server, head, callback) => {
|
|
193
256
|
server.emit("start", req, res, options.target || options.forward);
|
|
194
|
-
const
|
|
195
|
-
const
|
|
196
|
-
const
|
|
257
|
+
const http = nativeAgents.http;
|
|
258
|
+
const https = nativeAgents.https;
|
|
259
|
+
const maxRedirects = typeof options.followRedirects === "number" ? options.followRedirects : options.followRedirects ? 5 : 0;
|
|
197
260
|
if (options.forward) {
|
|
198
|
-
const forwardReq = (options.forward.protocol
|
|
261
|
+
const forwardReq = (isSSL.test(options.forward.protocol || "http") ? https : http).request(setupOutgoing(options.ssl || {}, options, req, "forward"));
|
|
199
262
|
const forwardError = createErrorHandler(forwardReq, options.forward);
|
|
200
263
|
req.on("error", forwardError);
|
|
201
264
|
forwardReq.on("error", forwardError);
|
|
@@ -205,31 +268,92 @@ const webIncomingMiddleware = [
|
|
|
205
268
|
return;
|
|
206
269
|
}
|
|
207
270
|
}
|
|
208
|
-
const proxyReq = (options.target.protocol
|
|
209
|
-
proxyReq.on("socket", (
|
|
271
|
+
const proxyReq = (isSSL.test(options.target.protocol || "http") ? https : http).request(setupOutgoing(options.ssl || {}, options, req));
|
|
272
|
+
proxyReq.on("socket", (_socket) => {
|
|
210
273
|
if (server && !proxyReq.getHeader("expect")) server.emit("proxyReq", proxyReq, req, res, options);
|
|
211
274
|
});
|
|
212
275
|
if (options.proxyTimeout) proxyReq.setTimeout(options.proxyTimeout, function() {
|
|
213
|
-
proxyReq.
|
|
276
|
+
proxyReq.destroy();
|
|
214
277
|
});
|
|
215
|
-
|
|
216
|
-
proxyReq.
|
|
278
|
+
res.on("close", function() {
|
|
279
|
+
if (!res.writableFinished) proxyReq.destroy();
|
|
217
280
|
});
|
|
218
281
|
const proxyError = createErrorHandler(proxyReq, options.target);
|
|
219
282
|
req.on("error", proxyError);
|
|
220
283
|
proxyReq.on("error", proxyError);
|
|
221
|
-
function createErrorHandler(
|
|
222
|
-
return function
|
|
223
|
-
if (req.socket
|
|
284
|
+
function createErrorHandler(proxyReq, url) {
|
|
285
|
+
return function proxyError(err) {
|
|
286
|
+
if (!req.socket?.writable && err.code === "ECONNRESET") {
|
|
224
287
|
server.emit("econnreset", err, req, res, url);
|
|
225
|
-
return
|
|
288
|
+
return proxyReq.destroy();
|
|
226
289
|
}
|
|
227
290
|
if (callback) callback(err, req, res, url);
|
|
228
291
|
else server.emit("error", err, req, res, url);
|
|
229
292
|
};
|
|
230
293
|
}
|
|
231
|
-
|
|
232
|
-
|
|
294
|
+
let bodyBuffer;
|
|
295
|
+
if (maxRedirects > 0) {
|
|
296
|
+
const chunks = [];
|
|
297
|
+
const source = options.buffer || req;
|
|
298
|
+
source.on("data", (chunk) => {
|
|
299
|
+
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
300
|
+
proxyReq.write(chunk);
|
|
301
|
+
});
|
|
302
|
+
source.on("end", () => {
|
|
303
|
+
bodyBuffer = Buffer.concat(chunks);
|
|
304
|
+
proxyReq.end();
|
|
305
|
+
});
|
|
306
|
+
source.on("error", (err) => {
|
|
307
|
+
proxyReq.destroy(err);
|
|
308
|
+
});
|
|
309
|
+
} else proxyReq.on("socket", (socket) => {
|
|
310
|
+
if (socket.pending) socket.on("connect", () => (options.buffer || req).pipe(proxyReq));
|
|
311
|
+
else (options.buffer || req).pipe(proxyReq);
|
|
312
|
+
});
|
|
313
|
+
function handleResponse(proxyRes, redirectCount, currentUrl) {
|
|
314
|
+
const statusCode = proxyRes.statusCode;
|
|
315
|
+
if (maxRedirects > 0 && redirectStatuses.has(statusCode) && redirectCount < maxRedirects && proxyRes.headers.location) {
|
|
316
|
+
proxyRes.resume();
|
|
317
|
+
const location = new URL(proxyRes.headers.location, currentUrl);
|
|
318
|
+
const preserveMethod = statusCode === 307 || statusCode === 308;
|
|
319
|
+
const redirectMethod = preserveMethod ? req.method || "GET" : "GET";
|
|
320
|
+
const isHTTPS = isSSL.test(location.protocol);
|
|
321
|
+
const agent = isHTTPS ? https : http;
|
|
322
|
+
const redirectHeaders = { ...req.headers };
|
|
323
|
+
if (options.headers) Object.assign(redirectHeaders, options.headers);
|
|
324
|
+
redirectHeaders.host = location.host;
|
|
325
|
+
if (location.host !== currentUrl.host) {
|
|
326
|
+
delete redirectHeaders.authorization;
|
|
327
|
+
delete redirectHeaders.cookie;
|
|
328
|
+
}
|
|
329
|
+
if (!preserveMethod) {
|
|
330
|
+
delete redirectHeaders["content-length"];
|
|
331
|
+
delete redirectHeaders["content-type"];
|
|
332
|
+
delete redirectHeaders["transfer-encoding"];
|
|
333
|
+
}
|
|
334
|
+
const redirectOpts = {
|
|
335
|
+
hostname: location.hostname,
|
|
336
|
+
port: location.port || (isHTTPS ? 443 : 80),
|
|
337
|
+
path: location.pathname + location.search,
|
|
338
|
+
method: redirectMethod,
|
|
339
|
+
headers: redirectHeaders,
|
|
340
|
+
agent: options.agent || false
|
|
341
|
+
};
|
|
342
|
+
if (isHTTPS) redirectOpts.rejectUnauthorized = options.secure === void 0 ? true : options.secure;
|
|
343
|
+
const redirectReq = agent.request(redirectOpts);
|
|
344
|
+
if (server && !redirectReq.getHeader("expect")) server.emit("proxyReq", redirectReq, req, res, options);
|
|
345
|
+
if (options.proxyTimeout) redirectReq.setTimeout(options.proxyTimeout, () => {
|
|
346
|
+
redirectReq.destroy();
|
|
347
|
+
});
|
|
348
|
+
const redirectError = createErrorHandler(redirectReq, location);
|
|
349
|
+
redirectReq.on("error", redirectError);
|
|
350
|
+
redirectReq.on("response", (nextRes) => {
|
|
351
|
+
handleResponse(nextRes, redirectCount + 1, location);
|
|
352
|
+
});
|
|
353
|
+
if (preserveMethod && bodyBuffer && bodyBuffer.length > 0) redirectReq.end(bodyBuffer);
|
|
354
|
+
else redirectReq.end();
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
233
357
|
if (server) server.emit("proxyRes", proxyRes, req, res);
|
|
234
358
|
if (!res.headersSent && !options.selfHandleResponse) {
|
|
235
359
|
for (const pass of webOutgoingMiddleware) if (pass(req, res, proxyRes, options)) break;
|
|
@@ -240,11 +364,21 @@ const webIncomingMiddleware = [
|
|
|
240
364
|
res.on("close", function() {
|
|
241
365
|
proxyRes.destroy();
|
|
242
366
|
});
|
|
367
|
+
proxyRes.on("close", function() {
|
|
368
|
+
if (!proxyRes.complete && !res.destroyed) res.destroy();
|
|
369
|
+
});
|
|
370
|
+
proxyRes.on("error", function(err) {
|
|
371
|
+
if (!res.destroyed) res.destroy(err);
|
|
372
|
+
if (server.listenerCount("error") > 0) server.emit("error", err, req, res, currentUrl);
|
|
373
|
+
});
|
|
243
374
|
proxyRes.on("end", function() {
|
|
244
375
|
if (server) server.emit("end", req, res, proxyRes);
|
|
245
376
|
});
|
|
246
377
|
if (!options.selfHandleResponse) proxyRes.pipe(res);
|
|
247
378
|
}
|
|
379
|
+
}
|
|
380
|
+
proxyReq.on("response", function(proxyRes) {
|
|
381
|
+
handleResponse(proxyRes, 0, options.target);
|
|
248
382
|
});
|
|
249
383
|
})
|
|
250
384
|
];
|
|
@@ -270,36 +404,42 @@ const websocketIncomingMiddleware = [
|
|
|
270
404
|
"for",
|
|
271
405
|
"port",
|
|
272
406
|
"proto"
|
|
273
|
-
])
|
|
407
|
+
]) {
|
|
408
|
+
const key = "x-forwarded-" + header;
|
|
409
|
+
if (!req.headers[key]) req.headers[key] = values[header];
|
|
410
|
+
}
|
|
274
411
|
}),
|
|
275
412
|
defineProxyMiddleware((req, socket, options, server, head, callback) => {
|
|
276
413
|
const createHttpHeader = function(line, headers) {
|
|
277
|
-
return Object.keys(headers).reduce(function(
|
|
414
|
+
return Object.keys(headers).reduce(function(head, key) {
|
|
278
415
|
const value = headers[key];
|
|
279
416
|
if (!Array.isArray(value)) {
|
|
280
|
-
|
|
281
|
-
return
|
|
417
|
+
head.push(key + ": " + value);
|
|
418
|
+
return head;
|
|
282
419
|
}
|
|
283
|
-
for (const element of value)
|
|
284
|
-
return
|
|
420
|
+
for (const element of value) head.push(key + ": " + element);
|
|
421
|
+
return head;
|
|
285
422
|
}, [line]).join("\r\n") + "\r\n\r\n";
|
|
286
423
|
};
|
|
287
424
|
setupSocket(socket);
|
|
288
425
|
if (head && head.length > 0) socket.unshift(head);
|
|
289
|
-
|
|
426
|
+
socket.on("error", onSocketError);
|
|
427
|
+
const proxyReq = (isSSL.test(options.target.protocol || "http") ? https : http).request(setupOutgoing(options.ssl || {}, options, req));
|
|
290
428
|
if (server) server.emit("proxyReqWs", proxyReq, req, socket, options, head);
|
|
291
429
|
proxyReq.on("error", onOutgoingError);
|
|
292
430
|
proxyReq.on("response", function(res) {
|
|
293
|
-
if (!res.upgrade) {
|
|
431
|
+
if (!res.upgrade) if (!socket.destroyed && socket.writable) {
|
|
294
432
|
socket.write(createHttpHeader("HTTP/" + res.httpVersion + " " + res.statusCode + " " + res.statusMessage, res.headers));
|
|
433
|
+
res.on("error", onOutgoingError);
|
|
295
434
|
res.pipe(socket);
|
|
296
|
-
}
|
|
435
|
+
} else res.resume();
|
|
297
436
|
});
|
|
298
437
|
proxyReq.on("upgrade", function(proxyRes, proxySocket, proxyHead) {
|
|
299
438
|
proxySocket.on("error", onOutgoingError);
|
|
300
439
|
proxySocket.on("end", function() {
|
|
301
440
|
server.emit("close", proxyRes, proxySocket, proxyHead);
|
|
302
441
|
});
|
|
442
|
+
socket.removeListener("error", onSocketError);
|
|
303
443
|
socket.on("error", function() {
|
|
304
444
|
proxySocket.end();
|
|
305
445
|
});
|
|
@@ -311,6 +451,11 @@ const websocketIncomingMiddleware = [
|
|
|
311
451
|
server.emit("proxySocket", proxySocket);
|
|
312
452
|
});
|
|
313
453
|
proxyReq.end();
|
|
454
|
+
function onSocketError(err) {
|
|
455
|
+
if (callback) callback(err, req, socket);
|
|
456
|
+
else server.emit("error", err, req, socket);
|
|
457
|
+
proxyReq.destroy();
|
|
458
|
+
}
|
|
314
459
|
function onOutgoingError(err) {
|
|
315
460
|
if (callback) callback(err, req, socket);
|
|
316
461
|
else server.emit("error", err, req, socket);
|
|
@@ -325,10 +470,6 @@ var ProxyServer = class extends EventEmitter {
|
|
|
325
470
|
options;
|
|
326
471
|
web;
|
|
327
472
|
ws;
|
|
328
|
-
/**
|
|
329
|
-
* Creates the proxy server with specified options.
|
|
330
|
-
* @param options - Config object passed to the proxy
|
|
331
|
-
*/
|
|
332
473
|
constructor(options = {}) {
|
|
333
474
|
super();
|
|
334
475
|
this.options = options || {};
|
|
@@ -336,25 +477,24 @@ var ProxyServer = class extends EventEmitter {
|
|
|
336
477
|
this.web = _createProxyFn("web", this);
|
|
337
478
|
this.ws = _createProxyFn("ws", this);
|
|
338
479
|
}
|
|
339
|
-
/**
|
|
340
|
-
* A function that wraps the object in a webserver, for your convenience
|
|
341
|
-
* @param port - Port to listen on
|
|
342
|
-
* @param hostname - The hostname to listen on
|
|
343
|
-
*/
|
|
344
480
|
listen(port, hostname) {
|
|
345
481
|
const closure = (req, res) => {
|
|
346
|
-
this.web(req, res);
|
|
482
|
+
return this.web(req, res);
|
|
347
483
|
};
|
|
348
|
-
|
|
484
|
+
if (this.options.http2) {
|
|
485
|
+
if (!this.options.ssl) throw new Error("HTTP/2 requires ssl option");
|
|
486
|
+
this._server = http2.createSecureServer({
|
|
487
|
+
...this.options.ssl,
|
|
488
|
+
allowHTTP1: true
|
|
489
|
+
}, closure);
|
|
490
|
+
} else if (this.options.ssl) this._server = https.createServer(this.options.ssl, closure);
|
|
491
|
+
else this._server = http.createServer(closure);
|
|
349
492
|
if (this.options.ws) this._server.on("upgrade", (req, socket, head) => {
|
|
350
|
-
this.
|
|
493
|
+
this.ws(req, socket, this.options, head).catch(() => {});
|
|
351
494
|
});
|
|
352
495
|
this._server.listen(port, hostname);
|
|
353
496
|
return this;
|
|
354
497
|
}
|
|
355
|
-
/**
|
|
356
|
-
* A function that closes the inner webserver and stops listening on given port
|
|
357
|
-
*/
|
|
358
498
|
close(callback) {
|
|
359
499
|
if (this._server) this._server.close((...args) => {
|
|
360
500
|
this._server = void 0;
|
|
@@ -363,7 +503,7 @@ var ProxyServer = class extends EventEmitter {
|
|
|
363
503
|
}
|
|
364
504
|
before(type, passName, pass) {
|
|
365
505
|
if (type !== "ws" && type !== "web") throw new Error("type must be `web` or `ws`");
|
|
366
|
-
const passes =
|
|
506
|
+
const passes = this._getPasses(type);
|
|
367
507
|
let i = false;
|
|
368
508
|
for (const [idx, v] of passes.entries()) if (v.name === passName) i = idx;
|
|
369
509
|
if (i === false) throw new Error("No such pass");
|
|
@@ -371,12 +511,15 @@ var ProxyServer = class extends EventEmitter {
|
|
|
371
511
|
}
|
|
372
512
|
after(type, passName, pass) {
|
|
373
513
|
if (type !== "ws" && type !== "web") throw new Error("type must be `web` or `ws`");
|
|
374
|
-
const passes =
|
|
514
|
+
const passes = this._getPasses(type);
|
|
375
515
|
let i = false;
|
|
376
516
|
for (const [idx, v] of passes.entries()) if (v.name === passName) i = idx;
|
|
377
517
|
if (i === false) throw new Error("No such pass");
|
|
378
518
|
passes.splice(i++, 0, pass);
|
|
379
519
|
}
|
|
520
|
+
_getPasses(type) {
|
|
521
|
+
return type === "ws" ? this._wsPasses : this._webPasses;
|
|
522
|
+
}
|
|
380
523
|
};
|
|
381
524
|
function createProxyServer(options = {}) {
|
|
382
525
|
return new ProxyServer(options);
|
|
@@ -388,7 +531,10 @@ function _createProxyFn(type, server) {
|
|
|
388
531
|
...server.options
|
|
389
532
|
};
|
|
390
533
|
for (const key of ["target", "forward"]) if (typeof requestOptions[key] === "string") requestOptions[key] = new URL(requestOptions[key]);
|
|
391
|
-
if (!requestOptions.target && !requestOptions.forward)
|
|
534
|
+
if (!requestOptions.target && !requestOptions.forward) {
|
|
535
|
+
this.emit("error", /* @__PURE__ */ new Error("Must provide a proper URL as target"));
|
|
536
|
+
return Promise.resolve();
|
|
537
|
+
}
|
|
392
538
|
let _resolve;
|
|
393
539
|
let _reject;
|
|
394
540
|
const callbackPromise = new Promise((resolve, reject) => {
|
|
@@ -401,15 +547,293 @@ function _createProxyFn(type, server) {
|
|
|
401
547
|
res.on("error", (error) => {
|
|
402
548
|
_reject(error);
|
|
403
549
|
});
|
|
404
|
-
for (const pass of
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
550
|
+
for (const pass of server._getPasses(type)) {
|
|
551
|
+
let stop;
|
|
552
|
+
try {
|
|
553
|
+
stop = pass(req, res, requestOptions, server, head, (error) => {
|
|
554
|
+
if (server.listenerCount("error") > 0) {
|
|
555
|
+
server.emit("error", error, req, res);
|
|
556
|
+
_resolve();
|
|
557
|
+
} else _reject(error);
|
|
558
|
+
});
|
|
559
|
+
} catch (error) {
|
|
560
|
+
if (server.listenerCount("error") > 0) {
|
|
561
|
+
server.emit("error", error, req, res);
|
|
562
|
+
_resolve();
|
|
563
|
+
} else _reject(error);
|
|
564
|
+
break;
|
|
565
|
+
}
|
|
566
|
+
if (stop) {
|
|
567
|
+
_resolve();
|
|
568
|
+
break;
|
|
569
|
+
}
|
|
409
570
|
}
|
|
410
571
|
return callbackPromise;
|
|
411
572
|
};
|
|
412
573
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
574
|
+
async function proxyFetch(addr, input, inputInit, opts) {
|
|
575
|
+
const resolvedAddr = parseAddr(addr);
|
|
576
|
+
let useHTTPS = false;
|
|
577
|
+
let addrBasePath = "";
|
|
578
|
+
if (typeof addr === "string" && !addr.startsWith("unix:")) {
|
|
579
|
+
const addrURL = new URL(addr);
|
|
580
|
+
useHTTPS = isSSL.test(addrURL.protocol);
|
|
581
|
+
if (addrURL.pathname && addrURL.pathname !== "/") addrBasePath = addrURL.pathname;
|
|
582
|
+
}
|
|
583
|
+
let url;
|
|
584
|
+
let init;
|
|
585
|
+
if (input instanceof Request) {
|
|
586
|
+
url = new URL(input.url);
|
|
587
|
+
init = {
|
|
588
|
+
...toInit(input),
|
|
589
|
+
...toInit(inputInit)
|
|
590
|
+
};
|
|
591
|
+
} else {
|
|
592
|
+
url = new URL(input);
|
|
593
|
+
init = toInit(inputInit);
|
|
594
|
+
}
|
|
595
|
+
init = {
|
|
596
|
+
redirect: "manual",
|
|
597
|
+
...init
|
|
598
|
+
};
|
|
599
|
+
if (init.body) init.duplex = "half";
|
|
600
|
+
const requestPath = url.pathname + url.search;
|
|
601
|
+
const path = addrBasePath ? joinURL(addrBasePath, requestPath) : requestPath;
|
|
602
|
+
const reqHeaders = {};
|
|
603
|
+
if (init.headers) if (!(init.headers instanceof Headers) && !Array.isArray(init.headers)) Object.assign(reqHeaders, init.headers);
|
|
604
|
+
else for (const [key, value] of init.headers) {
|
|
605
|
+
const existing = reqHeaders[key];
|
|
606
|
+
if (existing === void 0) reqHeaders[key] = value;
|
|
607
|
+
else reqHeaders[key] = Array.isArray(existing) ? [...existing, value] : [existing, value];
|
|
608
|
+
}
|
|
609
|
+
if (opts?.xfwd) {
|
|
610
|
+
if (!reqHeaders["x-forwarded-for"]) reqHeaders["x-forwarded-for"] = url.hostname;
|
|
611
|
+
if (!reqHeaders["x-forwarded-port"]) reqHeaders["x-forwarded-port"] = url.port || (url.protocol === "https:" ? "443" : "80");
|
|
612
|
+
if (!reqHeaders["x-forwarded-proto"]) reqHeaders["x-forwarded-proto"] = url.protocol.replace(":", "");
|
|
613
|
+
if (!reqHeaders["x-forwarded-host"]) reqHeaders["x-forwarded-host"] = url.host;
|
|
614
|
+
}
|
|
615
|
+
if (opts?.changeOrigin) if (resolvedAddr.socketPath) reqHeaders.host = "localhost";
|
|
616
|
+
else {
|
|
617
|
+
const targetHost = resolvedAddr.host || "localhost";
|
|
618
|
+
const targetPort = resolvedAddr.port;
|
|
619
|
+
reqHeaders.host = targetPort && targetPort !== (useHTTPS ? 443 : 80) ? `${targetHost}:${targetPort}` : targetHost;
|
|
620
|
+
}
|
|
621
|
+
const maxRedirects = typeof opts?.followRedirects === "number" ? opts.followRedirects : opts?.followRedirects ? 5 : 0;
|
|
622
|
+
const body = maxRedirects > 0 ? await _bufferBody(init.body) : _toNodeStream(init.body);
|
|
623
|
+
const agent = opts?.agent !== void 0 ? opts.agent || false : useHTTPS ? defaultAgents.https : defaultAgents.http;
|
|
624
|
+
const res = await _sendRequest(useHTTPS ? request$1 : request, init.method || "GET", path, reqHeaders, resolvedAddr, body, {
|
|
625
|
+
signal: init.signal || void 0,
|
|
626
|
+
agent,
|
|
627
|
+
timeout: opts?.timeout,
|
|
628
|
+
ssl: opts?.ssl,
|
|
629
|
+
maxRedirects,
|
|
630
|
+
redirectCount: 0,
|
|
631
|
+
originalHeaders: reqHeaders
|
|
632
|
+
});
|
|
633
|
+
const resHeaders = [];
|
|
634
|
+
const rawHeaders = res.rawHeaders;
|
|
635
|
+
for (let i = 0; i < rawHeaders.length; i += 2) {
|
|
636
|
+
const key = rawHeaders[i];
|
|
637
|
+
const keyLower = key.toLowerCase();
|
|
638
|
+
if (keyLower === "transfer-encoding" || keyLower === "keep-alive" || keyLower === "connection") continue;
|
|
639
|
+
resHeaders.push([key, rawHeaders[i + 1]]);
|
|
640
|
+
}
|
|
641
|
+
const hasBody = res.statusCode !== 204 && res.statusCode !== 304;
|
|
642
|
+
return new Response(hasBody ? Readable.toWeb(res) : null, {
|
|
643
|
+
status: res.statusCode,
|
|
644
|
+
statusText: res.statusMessage,
|
|
645
|
+
headers: resHeaders
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
function toInit(init) {
|
|
649
|
+
if (!init) return;
|
|
650
|
+
if (init instanceof Request) return {
|
|
651
|
+
method: init.method,
|
|
652
|
+
headers: init.headers,
|
|
653
|
+
body: init.body,
|
|
654
|
+
duplex: init.body ? "half" : void 0
|
|
655
|
+
};
|
|
656
|
+
return init;
|
|
657
|
+
}
|
|
658
|
+
function _toNodeStream(body) {
|
|
659
|
+
if (!body) return;
|
|
660
|
+
if (typeof body === "string") return Buffer.from(body);
|
|
661
|
+
if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) return Buffer.from(body);
|
|
662
|
+
if (body instanceof ReadableStream) return Readable.fromWeb(body);
|
|
663
|
+
if (body instanceof Blob) return Readable.fromWeb(body.stream());
|
|
664
|
+
return Buffer.from(String(body));
|
|
665
|
+
}
|
|
666
|
+
async function _bufferBody(body) {
|
|
667
|
+
if (!body) return;
|
|
668
|
+
if (typeof body === "string") return Buffer.from(body);
|
|
669
|
+
if (body instanceof ArrayBuffer || ArrayBuffer.isView(body)) return Buffer.from(body);
|
|
670
|
+
if (body instanceof ReadableStream) {
|
|
671
|
+
const readable = Readable.fromWeb(body);
|
|
672
|
+
const chunks = [];
|
|
673
|
+
for await (const chunk of readable) chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
674
|
+
return Buffer.concat(chunks);
|
|
675
|
+
}
|
|
676
|
+
if (body instanceof Blob) return Buffer.from(await body.arrayBuffer());
|
|
677
|
+
return Buffer.from(String(body));
|
|
678
|
+
}
|
|
679
|
+
const _redirectStatuses = new Set([
|
|
680
|
+
301,
|
|
681
|
+
302,
|
|
682
|
+
303,
|
|
683
|
+
307,
|
|
684
|
+
308
|
|
685
|
+
]);
|
|
686
|
+
function _sendRequest(doRequest, method, path, headers, addr, body, opts) {
|
|
687
|
+
return new Promise((resolve, reject) => {
|
|
688
|
+
const reqOpts = {
|
|
689
|
+
method,
|
|
690
|
+
path,
|
|
691
|
+
headers,
|
|
692
|
+
agent: opts.agent
|
|
693
|
+
};
|
|
694
|
+
if (addr.socketPath) reqOpts.socketPath = addr.socketPath;
|
|
695
|
+
else {
|
|
696
|
+
reqOpts.hostname = addr.host || "localhost";
|
|
697
|
+
reqOpts.port = addr.port;
|
|
698
|
+
}
|
|
699
|
+
if (opts.signal) reqOpts.signal = opts.signal;
|
|
700
|
+
if (opts.ssl) Object.assign(reqOpts, opts.ssl);
|
|
701
|
+
const req = doRequest(reqOpts, (res) => {
|
|
702
|
+
const statusCode = res.statusCode;
|
|
703
|
+
if (opts.maxRedirects > 0 && _redirectStatuses.has(statusCode) && opts.redirectCount < opts.maxRedirects && res.headers.location) {
|
|
704
|
+
res.resume();
|
|
705
|
+
const currentURL = new URL(path, `http://${addr.host || "localhost"}:${addr.port || 80}`);
|
|
706
|
+
const location = new URL(res.headers.location, currentURL);
|
|
707
|
+
const redirectHTTPS = isSSL.test(location.protocol);
|
|
708
|
+
const preserveMethod = statusCode === 307 || statusCode === 308;
|
|
709
|
+
const redirectMethod = preserveMethod ? method : "GET";
|
|
710
|
+
const redirectHeaders = { ...opts.originalHeaders };
|
|
711
|
+
redirectHeaders.host = location.host;
|
|
712
|
+
if (location.host !== currentURL.host) {
|
|
713
|
+
delete redirectHeaders.authorization;
|
|
714
|
+
delete redirectHeaders.cookie;
|
|
715
|
+
}
|
|
716
|
+
if (!preserveMethod) {
|
|
717
|
+
delete redirectHeaders["content-length"];
|
|
718
|
+
delete redirectHeaders["content-type"];
|
|
719
|
+
delete redirectHeaders["transfer-encoding"];
|
|
720
|
+
}
|
|
721
|
+
_sendRequest(redirectHTTPS ? request$1 : request, redirectMethod, location.pathname + location.search, redirectHeaders, {
|
|
722
|
+
host: location.hostname,
|
|
723
|
+
port: Number(location.port) || (redirectHTTPS ? 443 : 80)
|
|
724
|
+
}, preserveMethod ? body : void 0, {
|
|
725
|
+
...opts,
|
|
726
|
+
redirectCount: opts.redirectCount + 1
|
|
727
|
+
}).then(resolve, reject);
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
resolve(res);
|
|
731
|
+
});
|
|
732
|
+
req.on("error", reject);
|
|
733
|
+
if (opts.timeout) req.setTimeout(opts.timeout, () => {
|
|
734
|
+
req.destroy(/* @__PURE__ */ new Error("Proxy request timed out"));
|
|
735
|
+
});
|
|
736
|
+
if (body instanceof Readable) {
|
|
737
|
+
body.on("error", (err) => {
|
|
738
|
+
req.destroy(err);
|
|
739
|
+
reject(err);
|
|
740
|
+
});
|
|
741
|
+
body.pipe(req);
|
|
742
|
+
} else if (body) req.end(body);
|
|
743
|
+
else req.end();
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
function proxyUpgrade(addr, req, socket, head, opts) {
|
|
747
|
+
const resolvedAddr = parseAddr(addr);
|
|
748
|
+
let useSSL = false;
|
|
749
|
+
if (typeof addr === "string" && !addr.startsWith("unix:")) useSSL = isSSL.test(new URL(addr).protocol);
|
|
750
|
+
if (req.method !== "GET" || req.headers.upgrade?.toLowerCase() !== "websocket") {
|
|
751
|
+
socket.destroy();
|
|
752
|
+
return Promise.reject(/* @__PURE__ */ new Error("Not a valid WebSocket upgrade request"));
|
|
753
|
+
}
|
|
754
|
+
if (opts?.xfwd !== false) {
|
|
755
|
+
const xfFor = req.headers["x-forwarded-for"];
|
|
756
|
+
const xfPort = req.headers["x-forwarded-port"];
|
|
757
|
+
const xfProto = req.headers["x-forwarded-proto"];
|
|
758
|
+
req.headers["x-forwarded-for"] = `${xfFor ? `${xfFor},` : ""}${req.socket?.remoteAddress}`;
|
|
759
|
+
req.headers["x-forwarded-port"] = `${xfPort ? `${xfPort},` : ""}${getPort(req)}`;
|
|
760
|
+
req.headers["x-forwarded-proto"] = `${xfProto ? `${xfProto},` : ""}${hasEncryptedConnection(req) ? "wss" : "ws"}`;
|
|
761
|
+
}
|
|
762
|
+
const target = _buildTargetURL(resolvedAddr, useSSL);
|
|
763
|
+
const requestOptions = {
|
|
764
|
+
...opts,
|
|
765
|
+
target,
|
|
766
|
+
prependPath: opts?.prependPath !== false
|
|
767
|
+
};
|
|
768
|
+
const outgoing = setupOutgoing(requestOptions.ssl || {}, requestOptions, req);
|
|
769
|
+
const sock = socket;
|
|
770
|
+
return new Promise((resolve, reject) => {
|
|
771
|
+
let settled = false;
|
|
772
|
+
setupSocket(sock);
|
|
773
|
+
if (head && head.length > 0) sock.unshift(head);
|
|
774
|
+
sock.once("error", onSocketError);
|
|
775
|
+
const proxyReq = (isSSL.test(target.protocol) ? request$1 : request)(outgoing);
|
|
776
|
+
proxyReq.once("error", onOutgoingError);
|
|
777
|
+
proxyReq.once("response", (res) => {
|
|
778
|
+
if (!res.upgrade) {
|
|
779
|
+
if (!sock.destroyed && sock.writable) {
|
|
780
|
+
sock.write(_createHttpHeader(`HTTP/${res.httpVersion} ${res.statusCode} ${res.statusMessage}`, res.headers));
|
|
781
|
+
res.on("error", onOutgoingError);
|
|
782
|
+
res.pipe(sock);
|
|
783
|
+
} else res.resume();
|
|
784
|
+
if (!settled) {
|
|
785
|
+
settled = true;
|
|
786
|
+
reject(/* @__PURE__ */ new Error("Upstream server did not upgrade the connection"));
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
});
|
|
790
|
+
proxyReq.once("upgrade", (proxyRes, proxySocket, proxyHead) => {
|
|
791
|
+
proxySocket.once("error", onOutgoingError);
|
|
792
|
+
sock.removeListener("error", onSocketError);
|
|
793
|
+
sock.once("error", () => {
|
|
794
|
+
proxySocket.end();
|
|
795
|
+
});
|
|
796
|
+
setupSocket(proxySocket);
|
|
797
|
+
if (proxyHead && proxyHead.length > 0) proxySocket.unshift(proxyHead);
|
|
798
|
+
sock.write(_createHttpHeader("HTTP/1.1 101 Switching Protocols", proxyRes.headers));
|
|
799
|
+
proxySocket.pipe(sock).pipe(proxySocket);
|
|
800
|
+
settled = true;
|
|
801
|
+
resolve(proxySocket);
|
|
802
|
+
});
|
|
803
|
+
proxyReq.end();
|
|
804
|
+
function onSocketError(err) {
|
|
805
|
+
proxyReq.destroy();
|
|
806
|
+
if (!settled) {
|
|
807
|
+
settled = true;
|
|
808
|
+
reject(err);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
function onOutgoingError(err) {
|
|
812
|
+
sock.end();
|
|
813
|
+
if (!settled) {
|
|
814
|
+
settled = true;
|
|
815
|
+
reject(err);
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
function _buildTargetURL(addr, useSSL = false) {
|
|
821
|
+
const protocol = useSSL ? "https" : "http";
|
|
822
|
+
if (addr.socketPath) {
|
|
823
|
+
const url = new URL(`${protocol}://unix`);
|
|
824
|
+
url.socketPath = addr.socketPath;
|
|
825
|
+
return url;
|
|
826
|
+
}
|
|
827
|
+
return new URL(`${protocol}://${addr.host || "localhost"}${addr.port ? `:${addr.port}` : ""}`);
|
|
828
|
+
}
|
|
829
|
+
function _createHttpHeader(line, headers) {
|
|
830
|
+
let result = line;
|
|
831
|
+
for (const key of Object.keys(headers)) {
|
|
832
|
+
const value = headers[key];
|
|
833
|
+
if (value === void 0) continue;
|
|
834
|
+
if (Array.isArray(value)) for (const element of value) result += `\r\n${key}: ${element}`;
|
|
835
|
+
else result += `\r\n${key}: ${value}`;
|
|
836
|
+
}
|
|
837
|
+
return `${result}\r\n\r\n`;
|
|
838
|
+
}
|
|
839
|
+
export { proxyFetch as n, proxyUpgrade as r, createProxyServer as t };
|