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.
Files changed (297) hide show
  1. package/LICENSE +6 -0
  2. package/README.md +2 -2
  3. package/dist/THIRD-PARTY-LICENSES.md +1646 -0
  4. package/dist/_build/common.mjs +7261 -3812
  5. package/dist/_build/rolldown.mjs +32 -42
  6. package/dist/_build/rollup.mjs +28 -48
  7. package/dist/_build/vite.build.mjs +10 -10
  8. package/dist/_chunks/nitro.mjs +102 -327
  9. package/dist/_chunks/nitro2.mjs +8 -9
  10. package/dist/_chunks/nitro3.mjs +136 -0
  11. package/dist/_chunks/nitro4.mjs +127 -0
  12. package/dist/_chunks/utils.mjs +40 -29
  13. package/dist/_common.mjs +13 -25
  14. package/dist/_dev.d.mts +0 -3
  15. package/dist/{_chunks/dev.mjs → _dev.mjs} +132 -330
  16. package/dist/_libs/_.mjs +2 -0
  17. package/dist/_libs/_2.mjs +2 -0
  18. package/dist/_libs/_3.mjs +2 -0
  19. package/dist/_libs/_4.mjs +2 -0
  20. package/dist/_libs/_5.mjs +2 -0
  21. package/dist/_libs/_6.mjs +2 -0
  22. package/dist/_libs/_7.mjs +2 -0
  23. package/dist/_libs/c12+rc9.mjs +814 -0
  24. package/dist/_libs/{c12+giget+readdirp+chokidar.d.mts → c12+readdirp+chokidar.d.mts} +49 -40
  25. package/dist/_libs/citty.mjs +142 -41
  26. package/dist/_libs/commondir+is-reference.mjs +60 -56
  27. package/dist/_libs/compatx.d.mts +0 -2
  28. package/dist/_libs/compatx.mjs +1 -4
  29. package/dist/_libs/esbuild.d.mts +0 -1
  30. package/dist/_libs/escape-string-regexp.mjs +1 -4
  31. package/dist/_libs/{pluginutils+plugin-commonjs.d.mts → estree+pluginutils.d.mts} +0 -5
  32. package/dist/_libs/estree-walker.mjs +4 -92
  33. package/dist/_libs/exsolve.d.mts +1 -0
  34. package/dist/_libs/hasown+resolve+deepmerge.mjs +160 -246
  35. package/dist/_libs/httpxy.d.mts +20 -13
  36. package/dist/_libs/httpxy.mjs +519 -95
  37. package/dist/_libs/js-tokens.d.mts +1 -0
  38. package/dist/_libs/klona.mjs +1 -4
  39. package/dist/_libs/magic-string.d.mts +0 -2
  40. package/dist/_libs/mlly.d.mts +0 -2
  41. package/dist/_libs/nypm+tinyexec.mjs +822 -0
  42. package/dist/_libs/perfect-debounce.mjs +68 -0
  43. package/dist/_libs/pkg-types.d.mts +0 -3
  44. package/dist/_libs/plugin-alias.mjs +1 -5
  45. package/dist/_libs/plugin-inject.mjs +1 -7
  46. package/dist/_libs/plugin-json.mjs +1 -5
  47. package/dist/_libs/pluginutils.mjs +3 -35
  48. package/dist/_libs/readdirp+chokidar.mjs +187 -365
  49. package/dist/_libs/remapping.mjs +1 -5
  50. package/dist/_libs/resolve-uri+gen-mapping.mjs +15 -53
  51. package/dist/_libs/rou3.d.mts +1 -4
  52. package/dist/_libs/rou3.mjs +223 -78
  53. package/dist/_libs/std-env.d.mts +8 -2
  54. package/dist/_libs/strip-literal.d.mts +1 -0
  55. package/dist/_libs/tsconfck.mjs +21 -334
  56. package/dist/_libs/ultrahtml.mjs +3 -16
  57. package/dist/_libs/unimport+unplugin.mjs +244 -388
  58. package/dist/_libs/unplugin+unimport.d.mts +5 -15
  59. package/dist/_libs/unwasm.d.mts +0 -3
  60. package/dist/_presets.mjs +576 -488
  61. package/dist/builder.d.mts +5 -25
  62. package/dist/builder.mjs +3 -8
  63. package/dist/cli/_chunks/build.mjs +22 -25
  64. package/dist/cli/_chunks/common.mjs +1 -4
  65. package/dist/cli/_chunks/deploy.mjs +37 -0
  66. package/dist/cli/_chunks/dev.mjs +6 -11
  67. package/dist/cli/_chunks/docs.mjs +28 -0
  68. package/dist/cli/_chunks/list.mjs +4 -8
  69. package/dist/cli/_chunks/prepare.mjs +2 -6
  70. package/dist/cli/_chunks/preview.mjs +48 -0
  71. package/dist/cli/_chunks/run.mjs +7 -11
  72. package/dist/cli/_chunks/task.mjs +1 -5
  73. package/dist/cli/index.mjs +5 -6
  74. package/dist/docs/0.docs/0.index/index.md +56 -0
  75. package/dist/docs/0.docs/1.quick-start.md +110 -0
  76. package/dist/docs/0.docs/10.lifecycle.md +204 -0
  77. package/dist/docs/0.docs/11.openapi.md +291 -0
  78. package/dist/docs/0.docs/12.plugins.md +164 -0
  79. package/dist/docs/0.docs/13.tasks.md +277 -0
  80. package/dist/docs/0.docs/14.websocket.md +386 -0
  81. package/dist/docs/0.docs/15.migration.md +213 -0
  82. package/dist/docs/0.docs/16.nightly.md +31 -0
  83. package/dist/docs/0.docs/2.renderer.md +322 -0
  84. package/dist/docs/0.docs/3.routing.md +711 -0
  85. package/dist/docs/0.docs/4.server-entry.md +239 -0
  86. package/dist/docs/0.docs/5.cache.md +408 -0
  87. package/dist/docs/0.docs/6.storage.md +261 -0
  88. package/dist/docs/0.docs/7.assets.md +166 -0
  89. package/dist/docs/0.docs/8.configuration.md +256 -0
  90. package/dist/docs/0.docs/9.database.md +185 -0
  91. package/dist/docs/1.deploy/0.index/index.md +64 -0
  92. package/dist/docs/1.deploy/1.runtimes/0.node.md +63 -0
  93. package/dist/docs/1.deploy/1.runtimes/1.bun.md +15 -0
  94. package/dist/docs/1.deploy/1.runtimes/2.deno.md +19 -0
  95. package/dist/docs/1.deploy/2.providers/0.alwaysdata.md +50 -0
  96. package/dist/docs/1.deploy/2.providers/1.aws.md +47 -0
  97. package/dist/docs/1.deploy/2.providers/10.flightcontrol.md +67 -0
  98. package/dist/docs/1.deploy/2.providers/11.genezio.md +67 -0
  99. package/dist/docs/1.deploy/2.providers/12.github-pages.md +68 -0
  100. package/dist/docs/1.deploy/2.providers/13.gitlab-pages.md +37 -0
  101. package/dist/docs/1.deploy/2.providers/14.heroku.md +84 -0
  102. package/dist/docs/1.deploy/2.providers/15.iis.md +38 -0
  103. package/dist/docs/1.deploy/2.providers/16.koyeb.md +109 -0
  104. package/dist/docs/1.deploy/2.providers/17.netlify.md +47 -0
  105. package/dist/docs/1.deploy/2.providers/18.platform-sh.md +37 -0
  106. package/dist/docs/1.deploy/2.providers/19.render.md +37 -0
  107. package/dist/docs/1.deploy/2.providers/2.aws-amplify.md +81 -0
  108. package/dist/docs/1.deploy/2.providers/20.stormkit.md +24 -0
  109. package/dist/docs/1.deploy/2.providers/21.vercel.md +270 -0
  110. package/dist/docs/1.deploy/2.providers/22.zeabur.md +19 -0
  111. package/dist/docs/1.deploy/2.providers/23.zephyr.md +99 -0
  112. package/dist/docs/1.deploy/2.providers/24.zerops.md +102 -0
  113. package/dist/docs/1.deploy/2.providers/3.azure.md +72 -0
  114. package/dist/docs/1.deploy/2.providers/4.cleavr.md +33 -0
  115. package/dist/docs/1.deploy/2.providers/5.cloudflare.md +369 -0
  116. package/dist/docs/1.deploy/2.providers/6.deno-deploy.md +66 -0
  117. package/dist/docs/1.deploy/2.providers/7.digitalocean.md +46 -0
  118. package/dist/docs/1.deploy/2.providers/8.edgeone.md +20 -0
  119. package/dist/docs/1.deploy/2.providers/9.firebase.md +32 -0
  120. package/dist/docs/2.config/0.index/index.md +1221 -0
  121. package/dist/docs/3.examples/0.index/index.md +3 -0
  122. package/dist/docs/3.examples/1.api-routes.md +145 -0
  123. package/dist/docs/3.examples/10.hono.md +74 -0
  124. package/dist/docs/3.examples/11.import-alias.md +97 -0
  125. package/dist/docs/3.examples/12.middleware.md +91 -0
  126. package/dist/docs/3.examples/13.mono-jsx.md +68 -0
  127. package/dist/docs/3.examples/14.nano-jsx.md +70 -0
  128. package/dist/docs/3.examples/15.plugins.md +91 -0
  129. package/dist/docs/3.examples/16.renderer.md +113 -0
  130. package/dist/docs/3.examples/17.runtime-config.md +97 -0
  131. package/dist/docs/3.examples/18.server-fetch.md +87 -0
  132. package/dist/docs/3.examples/19.shiki.md +198 -0
  133. package/dist/docs/3.examples/2.auto-imports.md +92 -0
  134. package/dist/docs/3.examples/20.virtual-routes.md +74 -0
  135. package/dist/docs/3.examples/21.vite-nitro-plugin.md +79 -0
  136. package/dist/docs/3.examples/22.vite-rsc.md +1041 -0
  137. package/dist/docs/3.examples/23.vite-ssr-html.md +217 -0
  138. package/dist/docs/3.examples/24.vite-ssr-preact.md +247 -0
  139. package/dist/docs/3.examples/25.vite-ssr-react.md +226 -0
  140. package/dist/docs/3.examples/26.vite-ssr-solid.md +256 -0
  141. package/dist/docs/3.examples/27.vite-ssr-tsr-react.md +442 -0
  142. package/dist/docs/3.examples/28.vite-ssr-tss-react.md +444 -0
  143. package/dist/docs/3.examples/29.vite-ssr-vue-router.md +617 -0
  144. package/dist/docs/3.examples/3.cached-handler.md +81 -0
  145. package/dist/docs/3.examples/30.vite-trpc.md +335 -0
  146. package/dist/docs/3.examples/31.websocket.md +282 -0
  147. package/dist/docs/3.examples/4.custom-error-handler.md +98 -0
  148. package/dist/docs/3.examples/5.database.md +157 -0
  149. package/dist/docs/3.examples/6.elysia.md +70 -0
  150. package/dist/docs/3.examples/7.express.md +78 -0
  151. package/dist/docs/3.examples/8.fastify.md +79 -0
  152. package/dist/docs/3.examples/9.hello-world.md +68 -0
  153. package/dist/docs/README.md +86 -0
  154. package/dist/docs/index.md +121 -0
  155. package/dist/node_modules/@poppinss/dumper/build/formatters/html/main.js +8 -0
  156. package/dist/node_modules/@poppinss/dumper/package.json +1 -1
  157. package/dist/node_modules/@speed-highlight/core/dist/index.js +4 -4
  158. package/dist/node_modules/@speed-highlight/core/dist/terminal.js +2 -2
  159. package/dist/node_modules/@speed-highlight/core/package.json +1 -1
  160. package/dist/node_modules/cookie-es/dist/index.mjs +299 -250
  161. package/dist/node_modules/cookie-es/package.json +26 -23
  162. package/dist/node_modules/croner/dist/croner.js +1 -1
  163. package/dist/node_modules/croner/package.json +11 -1
  164. package/dist/node_modules/defu/dist/defu.mjs +2 -2
  165. package/dist/node_modules/defu/package.json +33 -28
  166. package/dist/node_modules/rendu/dist/_chunks/libs/cookie-es.mjs +151 -0
  167. package/dist/node_modules/rendu/dist/index.mjs +5 -112
  168. package/dist/node_modules/rendu/package.json +25 -24
  169. package/dist/node_modules/youch/build/helpers-B9BQYaS6.js +23 -0
  170. package/dist/node_modules/youch/build/index.js +204 -351
  171. package/dist/node_modules/youch/build/public/error_info/script.js +1 -1
  172. package/dist/node_modules/youch/build/public_dir-C5bujZKB.js +25 -0
  173. package/dist/node_modules/youch/build/src/templates/error_cause/main.js +44 -0
  174. package/dist/node_modules/youch/build/src/templates/error_info/main.js +72 -0
  175. package/dist/node_modules/youch/build/src/templates/error_metadata/main.js +65 -0
  176. package/dist/node_modules/youch/build/src/templates/error_stack/main.js +152 -0
  177. package/dist/node_modules/youch/build/src/templates/error_stack_source/main.js +46 -0
  178. package/dist/node_modules/youch/build/src/templates/header/main.js +24 -0
  179. package/dist/node_modules/youch/build/src/templates/layout/main.js +27 -0
  180. package/dist/node_modules/youch/package.json +35 -32
  181. package/dist/presets/_nitro/runtime/nitro-dev.mjs +12 -57
  182. package/dist/presets/_nitro/runtime/nitro-prerenderer.mjs +1 -0
  183. package/dist/presets/_nitro/runtime/service-worker.mjs +1 -2
  184. package/dist/presets/aws-lambda/runtime/_utils.mjs +6 -6
  185. package/dist/presets/aws-lambda/runtime/aws-lambda-streaming.mjs +3 -1
  186. package/dist/presets/azure/runtime/_utils.mjs +5 -5
  187. package/dist/presets/azure/runtime/azure-swa.mjs +5 -5
  188. package/dist/presets/bun/runtime/bun.mjs +9 -6
  189. package/dist/presets/cloudflare/runtime/_module-handler.mjs +1 -1
  190. package/dist/presets/cloudflare/runtime/cloudflare-durable.mjs +4 -4
  191. package/dist/presets/cloudflare/runtime/cloudflare-module.mjs +3 -3
  192. package/dist/presets/cloudflare/runtime/cloudflare-pages.mjs +2 -2
  193. package/dist/presets/cloudflare/runtime/plugin.dev.mjs +10 -21
  194. package/dist/presets/deno/runtime/deno-deploy.mjs +4 -4
  195. package/dist/presets/deno/runtime/deno-server.mjs +9 -6
  196. package/dist/presets/edgeone/runtime/edgeone.mjs +10 -0
  197. package/dist/presets/netlify/runtime/netlify-edge.mjs +2 -3
  198. package/dist/presets/netlify/runtime/netlify.mjs +1 -1
  199. package/dist/presets/node/runtime/node-cluster.mjs +5 -4
  200. package/dist/presets/node/runtime/node-middleware.mjs +1 -1
  201. package/dist/presets/node/runtime/node-server.mjs +8 -5
  202. package/dist/presets/stormkit/runtime/stormkit.mjs +1 -2
  203. package/dist/presets/vercel/runtime/cron-handler.mjs +25 -0
  204. package/dist/presets/vercel/runtime/queue-handler.mjs +21 -0
  205. package/dist/presets/vercel/runtime/vercel.node.mjs +3 -3
  206. package/dist/presets/vercel/runtime/vercel.web.mjs +3 -5
  207. package/dist/presets/winterjs/runtime/winterjs.mjs +10 -10
  208. package/dist/presets/zephyr/runtime/server.mjs +3 -0
  209. package/dist/runtime/internal/app.mjs +12 -11
  210. package/dist/runtime/internal/cache.d.mts +0 -4
  211. package/dist/runtime/internal/cache.mjs +32 -256
  212. package/dist/runtime/internal/context.d.mts +3 -1
  213. package/dist/runtime/internal/context.mjs +1 -9
  214. package/dist/runtime/internal/error/dev.d.mts +5 -4
  215. package/dist/runtime/internal/error/dev.mjs +47 -49
  216. package/dist/runtime/internal/error/hooks.d.mts +1 -1
  217. package/dist/runtime/internal/error/prod.d.mts +2 -5
  218. package/dist/runtime/internal/error/prod.mjs +19 -33
  219. package/dist/runtime/internal/error/utils.d.mts +4 -4
  220. package/dist/runtime/internal/meta.d.mts +1 -1
  221. package/dist/runtime/internal/plugin.d.mts +2 -2
  222. package/dist/runtime/internal/route-rules.d.mts +11 -4
  223. package/dist/runtime/internal/route-rules.mjs +15 -5
  224. package/dist/runtime/internal/routes/dev-tasks.d.mts +3 -2
  225. package/dist/runtime/internal/routes/dev-tasks.mjs +15 -10
  226. package/dist/runtime/internal/routes/openapi.mjs +2 -2
  227. package/dist/runtime/internal/routes/renderer-template.d.mts +1 -1
  228. package/dist/runtime/internal/routes/renderer-template.dev.d.mts +2 -1
  229. package/dist/runtime/internal/routes/scalar.mjs +3 -3
  230. package/dist/runtime/internal/routes/swagger.mjs +7 -4
  231. package/dist/runtime/internal/runtime-config.d.mts +1 -1
  232. package/dist/runtime/internal/runtime-config.mjs +2 -2
  233. package/dist/runtime/internal/static.mjs +5 -4
  234. package/dist/runtime/internal/task.d.mts +3 -1
  235. package/dist/runtime/internal/task.mjs +7 -7
  236. package/dist/runtime/internal/vite/dev-entry.mjs +6 -3
  237. package/dist/runtime/internal/vite/dev-worker.mjs +264 -0
  238. package/dist/runtime/meta.d.mts +1 -0
  239. package/dist/runtime/meta.mjs +2 -0
  240. package/dist/runtime/nitro.d.mts +2 -0
  241. package/dist/runtime/nitro.mjs +4 -2
  242. package/dist/runtime/virtual/error-handler.mjs +1 -1
  243. package/dist/runtime/virtual/renderer-template.mjs +1 -1
  244. package/dist/runtime/virtual/server-assets.d.mts +2 -1
  245. package/dist/runtime/virtual/tracing.d.mts +5 -0
  246. package/dist/runtime/virtual/tracing.mjs +1 -0
  247. package/dist/runtime/vite.d.mts +1 -1
  248. package/dist/types/index.d.mts +215 -195
  249. package/dist/types/index.mjs +1 -11
  250. package/dist/vite.d.mts +3 -8
  251. package/dist/vite.mjs +285 -253
  252. package/lib/tsconfig.json +3 -5
  253. package/package.json +97 -80
  254. package/dist/_libs/confbox.mjs +0 -2509
  255. package/dist/_libs/nypm+giget+tinyexec.mjs +0 -3603
  256. package/dist/_libs/rc9+c12+dotenv.mjs +0 -972
  257. package/dist/node_modules/hookable/dist/index.mjs +0 -266
  258. package/dist/node_modules/hookable/package.json +0 -52
  259. package/dist/node_modules/youch/build/chunk-4L7RY2JA.js +0 -42
  260. package/dist/node_modules/youch/build/chunk-7QV3D5YX.js +0 -83
  261. package/dist/node_modules/youch/build/chunk-AUGPHE32.js +0 -39
  262. package/dist/node_modules/youch/build/chunk-CM7DWJNZ.js +0 -44
  263. package/dist/node_modules/youch/build/chunk-EJH674NB.js +0 -223
  264. package/dist/node_modules/youch/build/chunk-OIJ3WD7L.js +0 -81
  265. package/dist/node_modules/youch/build/chunk-P36L72PL.js +0 -87
  266. package/dist/node_modules/youch/build/chunk-PE3GG3TN.js +0 -65
  267. package/dist/node_modules/youch/build/chunk-X53OIOJH.js +0 -70
  268. package/dist/presets/_nitro/runtime/nitro-dev.d.mts +0 -2
  269. package/dist/presets/_nitro/runtime/nitro-prerenderer.d.mts +0 -3
  270. package/dist/presets/_nitro/runtime/service-worker.d.mts +0 -2
  271. package/dist/presets/aws-amplify/runtime/aws-amplify.d.mts +0 -2
  272. package/dist/presets/aws-lambda/runtime/_utils.d.mts +0 -8
  273. package/dist/presets/aws-lambda/runtime/aws-lambda-streaming.d.mts +0 -2
  274. package/dist/presets/aws-lambda/runtime/aws-lambda.d.mts +0 -3
  275. package/dist/presets/azure/runtime/_utils.d.mts +0 -2
  276. package/dist/presets/azure/runtime/azure-swa.d.mts +0 -5
  277. package/dist/presets/bun/runtime/bun.d.mts +0 -3
  278. package/dist/presets/cloudflare/runtime/_module-handler.d.mts +0 -16
  279. package/dist/presets/cloudflare/runtime/cloudflare-durable.d.mts +0 -11
  280. package/dist/presets/cloudflare/runtime/cloudflare-module.d.mts +0 -3
  281. package/dist/presets/cloudflare/runtime/cloudflare-pages.d.mts +0 -20
  282. package/dist/presets/cloudflare/runtime/plugin.dev.d.mts +0 -3
  283. package/dist/presets/deno/runtime/deno-deploy.d.mts +0 -5
  284. package/dist/presets/deno/runtime/deno-server.d.mts +0 -3
  285. package/dist/presets/netlify/runtime/netlify-edge.d.mts +0 -3
  286. package/dist/presets/netlify/runtime/netlify.d.mts +0 -4
  287. package/dist/presets/node/runtime/node-cluster.d.mts +0 -3
  288. package/dist/presets/node/runtime/node-middleware.d.mts +0 -3
  289. package/dist/presets/node/runtime/node-server.d.mts +0 -3
  290. package/dist/presets/standard/runtime/server.d.mts +0 -3
  291. package/dist/presets/stormkit/runtime/stormkit.d.mts +0 -21
  292. package/dist/presets/vercel/runtime/isr.d.mts +0 -2
  293. package/dist/presets/vercel/runtime/vercel.node.d.mts +0 -3
  294. package/dist/presets/vercel/runtime/vercel.web.d.mts +0 -8
  295. package/dist/presets/winterjs/runtime/winterjs.d.mts +0 -2
  296. package/dist/presets/zeabur/runtime/zeabur.d.mts +0 -3
  297. package/dist/runtime/internal/vite/node-runner.mjs +0 -359
@@ -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
- //#region node_modules/.pnpm/httpxy@0.1.7/node_modules/httpxy/dist/index.mjs
7
- var dist_exports = /* @__PURE__ */ __exportAll({
8
- ProxyServer: () => ProxyServer,
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
- ]) outgoing[e] = options[forward || "target"][e];
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 (options.headers) outgoing.headers = {
30
- ...outgoing.headers,
31
- ...options.headers
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 || target.path || "" : "";
44
- const parsed = new URL(req.url, "http://localhost");
45
- let outgoingPath = options.toProxy ? req.url : parsed.pathname + parsed.search || "";
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
- outgoing.path = joinURL(targetPath, outgoingPath);
48
- if (options.changeOrigin) outgoing.headers.host = requiresPort(outgoing.port, options[forward || "target"].protocol) && !hasPort(outgoing.host) ? outgoing.host + ":" + outgoing.port : outgoing.host;
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 res = req.headers.host ? req.headers.host.match(/:(\d+)/) : "";
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
- return Boolean(req.connection.encrypted || req.connection.pair);
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.split(":")[0];
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([1278])$/;
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.httpVersion !== "2.0" && !proxyRes.headers.connection) proxyRes.headers.connection = req.headers.connection || "keep-alive";
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 = new URL(options.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) u.host = req.headers.host;
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
- let rewriteCookieDomainConfig = options.cookieDomainRewrite;
132
- let rewriteCookiePathConfig = options.cookiePathRewrite;
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
- res.setHeader(String(key).trim(), header);
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
- if (proxyRes.statusMessage) {
158
- res.statusCode = proxyRes.statusCode;
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
- ]) req.headers["x-forwarded-" + header] = (req.headers["x-forwarded-" + header] || "") + (req.headers["x-forwarded-" + header] ? "," : "") + values[header];
190
- req.headers["x-forwarded-host"] = req.headers["x-forwarded-host"] || req.headers.host || "";
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 agents = nativeAgents;
195
- const http$1 = agents.http;
196
- const https$1 = agents.https;
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 === "https:" ? https$1 : http$1).request(setupOutgoing(options.ssl || {}, options, req, "forward"));
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 === "https:" ? https$1 : http$1).request(setupOutgoing(options.ssl || {}, options, req));
209
- proxyReq.on("socket", (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.abort();
276
+ proxyReq.destroy();
214
277
  });
215
- req.on("aborted", function() {
216
- proxyReq.abort();
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(proxyReq2, url) {
222
- return function proxyError2(err) {
223
- if (req.socket.destroyed && err.code === "ECONNRESET") {
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 proxyReq2.abort();
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
- (options.buffer || req).pipe(proxyReq);
232
- proxyReq.on("response", function(proxyRes) {
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
- ]) req.headers["x-forwarded-" + header] = (req.headers["x-forwarded-" + header] || "") + (req.headers["x-forwarded-" + header] ? "," : "") + values[header];
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(head2, key) {
414
+ return Object.keys(headers).reduce(function(head, key) {
278
415
  const value = headers[key];
279
416
  if (!Array.isArray(value)) {
280
- head2.push(key + ": " + value);
281
- return head2;
417
+ head.push(key + ": " + value);
418
+ return head;
282
419
  }
283
- for (const element of value) head2.push(key + ": " + element);
284
- return head2;
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
- const proxyReq = (isSSL.test(options.target.protocol) ? https : http).request(setupOutgoing(options.ssl || {}, options, req));
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
- this._server = this.options.ssl ? https.createServer(this.options.ssl, closure) : http.createServer(closure);
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._ws(req, socket, head);
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 = type === "ws" ? this._wsPasses : this._webPasses;
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 = type === "ws" ? this._wsPasses : this._webPasses;
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) return this.emit("error", /* @__PURE__ */ new Error("Must provide a proper URL as target"));
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 type === "ws" ? server._wsPasses : server._webPasses) if (pass(req, res, requestOptions, server, head, (error) => {
405
- _reject(error);
406
- })) {
407
- _resolve();
408
- break;
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
- //#endregion
415
- export { dist_exports as n, createProxyServer as t };
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 };