@wooksjs/http-proxy 0.7.16 → 0.7.18
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/dist/index.cjs +37 -3
- package/dist/index.d.ts +7 -0
- package/dist/index.mjs +38 -4
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,42 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
let node_url = require("node:url");
|
|
3
2
|
let _wooksjs_event_http = require("@wooksjs/event-http");
|
|
4
3
|
|
|
5
4
|
//#region packages/http-proxy/src/proxy-utils.ts
|
|
5
|
+
const ALLOWED_PROXY_PROTOCOLS = new Set(["http:", "https:"]);
|
|
6
|
+
/**
|
|
7
|
+
* Resolves the upstream URL for a proxy target.
|
|
8
|
+
*
|
|
9
|
+
* The authority (protocol, host, port) is taken solely from `new URL(target)`.
|
|
10
|
+
* The pathname is intentionally NOT re-parsed against the origin: re-parsing a
|
|
11
|
+
* pathname that begins with `//` or `/\` would promote it to a protocol-relative
|
|
12
|
+
* authority, letting request-derived path data hijack the upstream host (SSRF).
|
|
13
|
+
* Only `http:`/`https:` targets are permitted.
|
|
14
|
+
*
|
|
15
|
+
* @param target - The proxy target URL string.
|
|
16
|
+
* @param allowedHosts - Optional allowlist of upstream hostnames. When provided,
|
|
17
|
+
* the resolved hostname must match one entry (string = case-insensitive exact
|
|
18
|
+
* match, RegExp = tested against the hostname); otherwise the request is
|
|
19
|
+
* rejected. An empty array denies every host.
|
|
20
|
+
* @returns A `URL` whose authority is fixed to the parsed target.
|
|
21
|
+
* @throws HttpError(502) if the target is not a valid `http:`/`https:` URL or its
|
|
22
|
+
* host is not in `allowedHosts`.
|
|
23
|
+
*/
|
|
24
|
+
function resolveProxyTarget(target, allowedHosts) {
|
|
25
|
+
let url;
|
|
26
|
+
try {
|
|
27
|
+
url = new URL(target);
|
|
28
|
+
} catch {
|
|
29
|
+
throw new _wooksjs_event_http.HttpError(502, "Invalid proxy target URL");
|
|
30
|
+
}
|
|
31
|
+
if (!ALLOWED_PROXY_PROTOCOLS.has(url.protocol)) throw new _wooksjs_event_http.HttpError(502, `Proxy target protocol "${url.protocol}" is not allowed`);
|
|
32
|
+
if (allowedHosts && !isHostAllowed(url.hostname, allowedHosts)) throw new _wooksjs_event_http.HttpError(502, `Proxy target host "${url.hostname}" is not allowed`);
|
|
33
|
+
url.hash = "";
|
|
34
|
+
return url;
|
|
35
|
+
}
|
|
36
|
+
function isHostAllowed(hostname, allowedHosts) {
|
|
37
|
+
const lower = hostname.toLowerCase();
|
|
38
|
+
return allowedHosts.some((entry) => typeof entry === "string" ? entry.toLowerCase() === lower : entry.test(hostname));
|
|
39
|
+
}
|
|
6
40
|
var IterableRecords = class {
|
|
7
41
|
constructor() {
|
|
8
42
|
this.index = 0;
|
|
@@ -102,8 +136,8 @@ function useProxy() {
|
|
|
102
136
|
const req = raw;
|
|
103
137
|
const logger = (0, _wooksjs_event_http.useLogger)();
|
|
104
138
|
return async function proxy(target, opts) {
|
|
105
|
-
const targetUrl =
|
|
106
|
-
const url =
|
|
139
|
+
const targetUrl = resolveProxyTarget(target, opts?.allowedHosts);
|
|
140
|
+
const url = targetUrl.toString();
|
|
107
141
|
const modifiedHeaders = {
|
|
108
142
|
...req.headers,
|
|
109
143
|
host: targetUrl.hostname
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,13 @@ interface TWooksProxyControls {
|
|
|
11
11
|
interface TWooksProxyOptions {
|
|
12
12
|
/** Override the HTTP method used for the proxied request. */
|
|
13
13
|
method?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Allowlist of upstream hostnames. When set, the resolved target host must match
|
|
16
|
+
* one entry (string = case-insensitive exact match, RegExp = tested against the
|
|
17
|
+
* hostname) or the request is rejected with `502`. Use this when the target is
|
|
18
|
+
* built from request input. An empty array denies every host.
|
|
19
|
+
*/
|
|
20
|
+
allowedHosts?: Array<string | RegExp>;
|
|
14
21
|
/** Controls for filtering/transforming outgoing request headers. */
|
|
15
22
|
reqHeaders?: TWooksProxyControls;
|
|
16
23
|
/** Controls for filtering/transforming outgoing request cookies. */
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,41 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useLogger, useRequest, useResponse } from "@wooksjs/event-http";
|
|
1
|
+
import { HttpError, useLogger, useRequest, useResponse } from "@wooksjs/event-http";
|
|
3
2
|
|
|
4
3
|
//#region packages/http-proxy/src/proxy-utils.ts
|
|
4
|
+
const ALLOWED_PROXY_PROTOCOLS = new Set(["http:", "https:"]);
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the upstream URL for a proxy target.
|
|
7
|
+
*
|
|
8
|
+
* The authority (protocol, host, port) is taken solely from `new URL(target)`.
|
|
9
|
+
* The pathname is intentionally NOT re-parsed against the origin: re-parsing a
|
|
10
|
+
* pathname that begins with `//` or `/\` would promote it to a protocol-relative
|
|
11
|
+
* authority, letting request-derived path data hijack the upstream host (SSRF).
|
|
12
|
+
* Only `http:`/`https:` targets are permitted.
|
|
13
|
+
*
|
|
14
|
+
* @param target - The proxy target URL string.
|
|
15
|
+
* @param allowedHosts - Optional allowlist of upstream hostnames. When provided,
|
|
16
|
+
* the resolved hostname must match one entry (string = case-insensitive exact
|
|
17
|
+
* match, RegExp = tested against the hostname); otherwise the request is
|
|
18
|
+
* rejected. An empty array denies every host.
|
|
19
|
+
* @returns A `URL` whose authority is fixed to the parsed target.
|
|
20
|
+
* @throws HttpError(502) if the target is not a valid `http:`/`https:` URL or its
|
|
21
|
+
* host is not in `allowedHosts`.
|
|
22
|
+
*/
|
|
23
|
+
function resolveProxyTarget(target, allowedHosts) {
|
|
24
|
+
let url;
|
|
25
|
+
try {
|
|
26
|
+
url = new URL(target);
|
|
27
|
+
} catch {
|
|
28
|
+
throw new HttpError(502, "Invalid proxy target URL");
|
|
29
|
+
}
|
|
30
|
+
if (!ALLOWED_PROXY_PROTOCOLS.has(url.protocol)) throw new HttpError(502, `Proxy target protocol "${url.protocol}" is not allowed`);
|
|
31
|
+
if (allowedHosts && !isHostAllowed(url.hostname, allowedHosts)) throw new HttpError(502, `Proxy target host "${url.hostname}" is not allowed`);
|
|
32
|
+
url.hash = "";
|
|
33
|
+
return url;
|
|
34
|
+
}
|
|
35
|
+
function isHostAllowed(hostname, allowedHosts) {
|
|
36
|
+
const lower = hostname.toLowerCase();
|
|
37
|
+
return allowedHosts.some((entry) => typeof entry === "string" ? entry.toLowerCase() === lower : entry.test(hostname));
|
|
38
|
+
}
|
|
5
39
|
var IterableRecords = class {
|
|
6
40
|
constructor() {
|
|
7
41
|
this.index = 0;
|
|
@@ -101,8 +135,8 @@ function useProxy() {
|
|
|
101
135
|
const req = raw;
|
|
102
136
|
const logger = useLogger();
|
|
103
137
|
return async function proxy(target, opts) {
|
|
104
|
-
const targetUrl =
|
|
105
|
-
const url =
|
|
138
|
+
const targetUrl = resolveProxyTarget(target, opts?.allowedHosts);
|
|
139
|
+
const url = targetUrl.toString();
|
|
106
140
|
const modifiedHeaders = {
|
|
107
141
|
...req.headers,
|
|
108
142
|
host: targetUrl.hostname
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wooksjs/http-proxy",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.18",
|
|
4
4
|
"description": "Proxy Wooks composable",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"api",
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"typescript": "^5.9.3",
|
|
44
44
|
"vitest": "^3.2.4",
|
|
45
|
-
"@wooksjs/event-http": "^0.7.
|
|
45
|
+
"@wooksjs/event-http": "^0.7.18"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
|
-
"@wooksjs/event-http": "^0.7.
|
|
48
|
+
"@wooksjs/event-http": "^0.7.18"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "rolldown -c ../../rolldown.config.mjs"
|