@claxedo/sandbox-manager 0.6.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -15
- package/dist/checkpoint-manager.d.ts +47 -0
- package/dist/checkpoint-manager.mjs +116 -0
- package/dist/daytona-allow-list.d.ts +11 -0
- package/dist/daytona-allow-list.mjs +5 -1
- package/dist/driver-catalog.d.ts +5 -52
- package/dist/driver-catalog.mjs +263 -121
- package/dist/drivers/box.mjs +309 -39
- package/dist/drivers/cloudflare.d.ts +18 -7
- package/dist/drivers/cloudflare.mjs +423 -34
- package/dist/drivers/daytona.d.ts +82 -13
- package/dist/drivers/daytona.mjs +495 -45
- package/dist/drivers/docker.mjs +284 -38
- package/dist/drivers/exe.d.ts +26 -0
- package/dist/drivers/exe.mjs +492 -0
- package/dist/drivers/fetch-bridge.mjs +29 -5
- package/dist/drivers/modal.d.ts +2 -5
- package/dist/drivers/modal.mjs +296 -46
- package/dist/drivers/transient-error.d.ts +11 -0
- package/dist/drivers/vercel.d.ts +27 -11
- package/dist/drivers/vercel.mjs +339 -59
- package/dist/hosted-network-policy.d.ts +87 -0
- package/dist/hosted-network-policy.mjs +61 -0
- package/dist/image-name.mjs +34 -0
- package/dist/image.d.ts +18 -3
- package/dist/image.mjs +47 -32
- package/dist/index.d.ts +281 -17
- package/dist/index.mjs +393 -26
- package/dist/json.d.ts +13 -0
- package/dist/lease-policy.d.ts +6 -3
- package/dist/lease-policy.mjs +213 -54
- package/dist/lease-types.d.ts +17 -3
- package/dist/runtime-env.d.ts +12 -1
- package/dist/runtime-env.mjs +14 -0
- package/dist/runtime-version.mjs +1 -9
- package/dist/service-url-exposure.d.ts +1 -2
- package/dist/service-url-exposure.mjs +1 -17
- package/dist/stores/memory.mjs +39 -4
- package/package.json +67 -51
- package/dist/drivers/cloudflare-egress.d.ts +0 -40
- package/dist/drivers/cloudflare-egress.mjs +0 -113
package/package.json
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
"name": "@claxedo/sandbox-manager",
|
|
3
|
-
"version": "0.6.0",
|
|
4
2
|
"type": "module",
|
|
5
3
|
"description": "Sandbox lifecycle manager with epoch-based leases and pluggable drivers for Daytona, Modal, Vercel Sandbox, Cloudflare, Box, and Docker",
|
|
6
4
|
"license": "MIT",
|
|
@@ -24,137 +22,151 @@
|
|
|
24
22
|
"types": "./dist/index.d.ts",
|
|
25
23
|
"exports": {
|
|
26
24
|
".": {
|
|
25
|
+
"development": "./src/index.ts",
|
|
26
|
+
"bun": "./src/index.ts",
|
|
27
27
|
"types": "./dist/index.d.ts",
|
|
28
|
-
"bun": "./dist/index.mjs",
|
|
29
|
-
"development": "./dist/index.mjs",
|
|
30
28
|
"import": "./dist/index.mjs",
|
|
31
29
|
"default": "./dist/index.mjs"
|
|
32
30
|
},
|
|
33
31
|
"./command": {
|
|
32
|
+
"development": "./src/command.ts",
|
|
33
|
+
"bun": "./src/command.ts",
|
|
34
34
|
"types": "./dist/command.d.ts",
|
|
35
|
-
"bun": "./dist/command.mjs",
|
|
36
|
-
"development": "./dist/command.mjs",
|
|
37
35
|
"import": "./dist/command.mjs",
|
|
38
36
|
"default": "./dist/command.mjs"
|
|
39
37
|
},
|
|
40
38
|
"./constants": {
|
|
39
|
+
"development": "./src/constants.ts",
|
|
40
|
+
"bun": "./src/constants.ts",
|
|
41
41
|
"types": "./dist/constants.d.ts",
|
|
42
|
-
"bun": "./dist/constants.mjs",
|
|
43
|
-
"development": "./dist/constants.mjs",
|
|
44
42
|
"import": "./dist/constants.mjs",
|
|
45
43
|
"default": "./dist/constants.mjs"
|
|
46
44
|
},
|
|
45
|
+
"./checkpoint-manager": {
|
|
46
|
+
"development": "./src/checkpoint-manager.ts",
|
|
47
|
+
"bun": "./src/checkpoint-manager.ts",
|
|
48
|
+
"types": "./dist/checkpoint-manager.d.ts",
|
|
49
|
+
"import": "./dist/checkpoint-manager.mjs",
|
|
50
|
+
"default": "./dist/checkpoint-manager.mjs"
|
|
51
|
+
},
|
|
47
52
|
"./defaults": {
|
|
53
|
+
"development": "./src/defaults.ts",
|
|
54
|
+
"bun": "./src/defaults.ts",
|
|
48
55
|
"types": "./dist/defaults.d.ts",
|
|
49
|
-
"bun": "./dist/defaults.mjs",
|
|
50
|
-
"development": "./dist/defaults.mjs",
|
|
51
56
|
"import": "./dist/defaults.mjs",
|
|
52
57
|
"default": "./dist/defaults.mjs"
|
|
53
58
|
},
|
|
54
59
|
"./driver-catalog": {
|
|
60
|
+
"development": "./src/driver-catalog.ts",
|
|
61
|
+
"bun": "./src/driver-catalog.ts",
|
|
55
62
|
"types": "./dist/driver-catalog.d.ts",
|
|
56
|
-
"bun": "./dist/driver-catalog.mjs",
|
|
57
|
-
"development": "./dist/driver-catalog.mjs",
|
|
58
63
|
"import": "./dist/driver-catalog.mjs",
|
|
59
64
|
"default": "./dist/driver-catalog.mjs"
|
|
60
65
|
},
|
|
61
66
|
"./drivers/box": {
|
|
67
|
+
"development": "./src/drivers/box.ts",
|
|
68
|
+
"bun": "./src/drivers/box.ts",
|
|
62
69
|
"types": "./dist/drivers/box.d.ts",
|
|
63
|
-
"bun": "./dist/drivers/box.mjs",
|
|
64
|
-
"development": "./dist/drivers/box.mjs",
|
|
65
70
|
"import": "./dist/drivers/box.mjs",
|
|
66
71
|
"default": "./dist/drivers/box.mjs"
|
|
67
72
|
},
|
|
73
|
+
"./drivers/exe": {
|
|
74
|
+
"development": "./src/drivers/exe.ts",
|
|
75
|
+
"bun": "./src/drivers/exe.ts",
|
|
76
|
+
"types": "./dist/drivers/exe.d.ts",
|
|
77
|
+
"import": "./dist/drivers/exe.mjs",
|
|
78
|
+
"default": "./dist/drivers/exe.mjs"
|
|
79
|
+
},
|
|
68
80
|
"./drivers/cloudflare": {
|
|
81
|
+
"development": "./src/drivers/cloudflare.ts",
|
|
82
|
+
"bun": "./src/drivers/cloudflare.ts",
|
|
69
83
|
"types": "./dist/drivers/cloudflare.d.ts",
|
|
70
|
-
"bun": "./dist/drivers/cloudflare.mjs",
|
|
71
|
-
"development": "./dist/drivers/cloudflare.mjs",
|
|
72
84
|
"import": "./dist/drivers/cloudflare.mjs",
|
|
73
85
|
"default": "./dist/drivers/cloudflare.mjs"
|
|
74
86
|
},
|
|
75
87
|
"./drivers/daytona": {
|
|
88
|
+
"development": "./src/drivers/daytona.ts",
|
|
89
|
+
"bun": "./src/drivers/daytona.ts",
|
|
76
90
|
"types": "./dist/drivers/daytona.d.ts",
|
|
77
|
-
"bun": "./dist/drivers/daytona.mjs",
|
|
78
|
-
"development": "./dist/drivers/daytona.mjs",
|
|
79
91
|
"import": "./dist/drivers/daytona.mjs",
|
|
80
92
|
"default": "./dist/drivers/daytona.mjs"
|
|
81
93
|
},
|
|
82
94
|
"./drivers/docker": {
|
|
95
|
+
"development": "./src/drivers/docker.ts",
|
|
96
|
+
"bun": "./src/drivers/docker.ts",
|
|
83
97
|
"types": "./dist/drivers/docker.d.ts",
|
|
84
|
-
"bun": "./dist/drivers/docker.mjs",
|
|
85
|
-
"development": "./dist/drivers/docker.mjs",
|
|
86
98
|
"import": "./dist/drivers/docker.mjs",
|
|
87
99
|
"default": "./dist/drivers/docker.mjs"
|
|
88
100
|
},
|
|
89
101
|
"./drivers/fetch-bridge": {
|
|
102
|
+
"development": "./src/drivers/fetch-bridge.ts",
|
|
103
|
+
"bun": "./src/drivers/fetch-bridge.ts",
|
|
90
104
|
"types": "./dist/drivers/fetch-bridge.d.ts",
|
|
91
|
-
"bun": "./dist/drivers/fetch-bridge.mjs",
|
|
92
|
-
"development": "./dist/drivers/fetch-bridge.mjs",
|
|
93
105
|
"import": "./dist/drivers/fetch-bridge.mjs",
|
|
94
106
|
"default": "./dist/drivers/fetch-bridge.mjs"
|
|
95
107
|
},
|
|
96
108
|
"./drivers/modal": {
|
|
109
|
+
"development": "./src/drivers/modal.ts",
|
|
110
|
+
"bun": "./src/drivers/modal.ts",
|
|
97
111
|
"types": "./dist/drivers/modal.d.ts",
|
|
98
|
-
"bun": "./dist/drivers/modal.mjs",
|
|
99
|
-
"development": "./dist/drivers/modal.mjs",
|
|
100
112
|
"import": "./dist/drivers/modal.mjs",
|
|
101
113
|
"default": "./dist/drivers/modal.mjs"
|
|
102
114
|
},
|
|
103
115
|
"./drivers/vercel": {
|
|
116
|
+
"development": "./src/drivers/vercel.ts",
|
|
117
|
+
"bun": "./src/drivers/vercel.ts",
|
|
104
118
|
"types": "./dist/drivers/vercel.d.ts",
|
|
105
|
-
"bun": "./dist/drivers/vercel.mjs",
|
|
106
|
-
"development": "./dist/drivers/vercel.mjs",
|
|
107
119
|
"import": "./dist/drivers/vercel.mjs",
|
|
108
120
|
"default": "./dist/drivers/vercel.mjs"
|
|
109
121
|
},
|
|
110
122
|
"./image": {
|
|
123
|
+
"development": "./src/image.ts",
|
|
124
|
+
"bun": "./src/image.ts",
|
|
111
125
|
"types": "./dist/image.d.ts",
|
|
112
|
-
"bun": "./dist/image.mjs",
|
|
113
|
-
"development": "./dist/image.mjs",
|
|
114
126
|
"import": "./dist/image.mjs",
|
|
115
127
|
"default": "./dist/image.mjs"
|
|
116
128
|
},
|
|
129
|
+
"./image-name": {
|
|
130
|
+
"development": "./src/image-name.ts",
|
|
131
|
+
"bun": "./src/image-name.ts",
|
|
132
|
+
"types": "./dist/image-name.d.ts",
|
|
133
|
+
"import": "./dist/image-name.mjs",
|
|
134
|
+
"default": "./dist/image-name.mjs"
|
|
135
|
+
},
|
|
117
136
|
"./lease-policy": {
|
|
137
|
+
"development": "./src/lease-policy.ts",
|
|
138
|
+
"bun": "./src/lease-policy.ts",
|
|
118
139
|
"types": "./dist/lease-policy.d.ts",
|
|
119
|
-
"bun": "./dist/lease-policy.mjs",
|
|
120
|
-
"development": "./dist/lease-policy.mjs",
|
|
121
140
|
"import": "./dist/lease-policy.mjs",
|
|
122
141
|
"default": "./dist/lease-policy.mjs"
|
|
123
142
|
},
|
|
124
143
|
"./lease-types": {
|
|
144
|
+
"development": "./src/lease-types.ts",
|
|
145
|
+
"bun": "./src/lease-types.ts",
|
|
125
146
|
"types": "./dist/lease-types.d.ts",
|
|
126
|
-
"bun": "./dist/lease-types.mjs",
|
|
127
|
-
"development": "./dist/lease-types.mjs",
|
|
128
147
|
"import": "./dist/lease-types.mjs",
|
|
129
148
|
"default": "./dist/lease-types.mjs"
|
|
130
149
|
},
|
|
131
150
|
"./runtime-env": {
|
|
151
|
+
"development": "./src/runtime-env.ts",
|
|
152
|
+
"bun": "./src/runtime-env.ts",
|
|
132
153
|
"types": "./dist/runtime-env.d.ts",
|
|
133
|
-
"bun": "./dist/runtime-env.mjs",
|
|
134
|
-
"development": "./dist/runtime-env.mjs",
|
|
135
154
|
"import": "./dist/runtime-env.mjs",
|
|
136
155
|
"default": "./dist/runtime-env.mjs"
|
|
137
156
|
},
|
|
138
157
|
"./service-url-exposure": {
|
|
158
|
+
"development": "./src/service-url-exposure.ts",
|
|
159
|
+
"bun": "./src/service-url-exposure.ts",
|
|
139
160
|
"types": "./dist/service-url-exposure.d.ts",
|
|
140
|
-
"bun": "./dist/service-url-exposure.mjs",
|
|
141
|
-
"development": "./dist/service-url-exposure.mjs",
|
|
142
161
|
"import": "./dist/service-url-exposure.mjs",
|
|
143
162
|
"default": "./dist/service-url-exposure.mjs"
|
|
144
163
|
},
|
|
145
164
|
"./stores/memory": {
|
|
165
|
+
"development": "./src/stores/memory.ts",
|
|
166
|
+
"bun": "./src/stores/memory.ts",
|
|
146
167
|
"types": "./dist/stores/memory.d.ts",
|
|
147
|
-
"bun": "./dist/stores/memory.mjs",
|
|
148
|
-
"development": "./dist/stores/memory.mjs",
|
|
149
168
|
"import": "./dist/stores/memory.mjs",
|
|
150
169
|
"default": "./dist/stores/memory.mjs"
|
|
151
|
-
},
|
|
152
|
-
"./drivers/cloudflare-egress": {
|
|
153
|
-
"types": "./dist/drivers/cloudflare-egress.d.ts",
|
|
154
|
-
"bun": "./dist/drivers/cloudflare-egress.mjs",
|
|
155
|
-
"development": "./dist/drivers/cloudflare-egress.mjs",
|
|
156
|
-
"import": "./dist/drivers/cloudflare-egress.mjs",
|
|
157
|
-
"default": "./dist/drivers/cloudflare-egress.mjs"
|
|
158
170
|
}
|
|
159
171
|
},
|
|
160
172
|
"files": [
|
|
@@ -165,16 +177,20 @@
|
|
|
165
177
|
"publishConfig": {
|
|
166
178
|
"access": "public"
|
|
167
179
|
},
|
|
168
|
-
"
|
|
169
|
-
|
|
170
|
-
"@vercel/sandbox": "1.10.2",
|
|
171
|
-
"modal": "0.7.5"
|
|
172
|
-
},
|
|
180
|
+
"name": "@claxedo/sandbox-manager",
|
|
181
|
+
"version": "0.9.0",
|
|
173
182
|
"scripts": {
|
|
174
183
|
"build": "tsx scripts/build.ts",
|
|
175
184
|
"prepublishOnly": "npm run build",
|
|
176
185
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
177
|
-
"test": "bun test src"
|
|
186
|
+
"test": "mkdir -p .artifacts/unit && node ../../scripts/test-deadline.mjs bun test src --reporter=junit --reporter-outfile=.artifacts/unit/junit.xml"
|
|
187
|
+
},
|
|
188
|
+
"dependencies": {
|
|
189
|
+
"@claxedo/helpers": "0.1.0",
|
|
190
|
+
"@claxedo/sandbox-contract": "0.8.0",
|
|
191
|
+
"@daytona/sdk": "0.211.2",
|
|
192
|
+
"@vercel/sandbox": "3.3.0",
|
|
193
|
+
"modal": "0.10.1"
|
|
178
194
|
},
|
|
179
195
|
"devDependencies": {
|
|
180
196
|
"@tsconfig/node-lts": "22.0.4",
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
export type EgressTokenClaims = {
|
|
2
|
-
/** Sandbox the token is bound to. */
|
|
3
|
-
sub: string;
|
|
4
|
-
/** Hosts the sandbox may reach through the broker. */
|
|
5
|
-
hosts: string[];
|
|
6
|
-
/** Expiry (epoch seconds). */
|
|
7
|
-
exp: number;
|
|
8
|
-
};
|
|
9
|
-
/** Mint a short-lived HS256 token binding a sandbox to its brokered hosts. Carries NO secret values. */
|
|
10
|
-
export declare function mintEgressToken(input: {
|
|
11
|
-
sandboxId: string;
|
|
12
|
-
hosts: string[];
|
|
13
|
-
signingSecret: string;
|
|
14
|
-
ttlSeconds?: number;
|
|
15
|
-
now?: () => number;
|
|
16
|
-
}): Promise<string>;
|
|
17
|
-
/** Verify a token and return its claims, or null if invalid/expired. */
|
|
18
|
-
export declare function verifyEgressToken(token: string, signingSecret: string, now?: () => number): Promise<EgressTokenClaims | null>;
|
|
19
|
-
/** How the sandbox names its egress target: header carries the absolute upstream URL. */
|
|
20
|
-
export declare const EGRESS_TARGET_HEADER = "x-claxedo-egress-target";
|
|
21
|
-
/** Resolves the brokered credential for a (sandbox, host) pair — Worker-side only, never the sandbox. */
|
|
22
|
-
export type EgressSecretResolver = (sandboxId: string, host: string) => Promise<{
|
|
23
|
-
header: string;
|
|
24
|
-
value: string;
|
|
25
|
-
} | undefined> | {
|
|
26
|
-
header: string;
|
|
27
|
-
value: string;
|
|
28
|
-
} | undefined;
|
|
29
|
-
/**
|
|
30
|
-
* Handle one egress-proxy request from a sandbox: validate the JWT, confirm
|
|
31
|
-
* the target host is allowed, inject the brokered credential as its header,
|
|
32
|
-
* and forward. The credential is read from `resolveSecret` (Worker store) and
|
|
33
|
-
* never round-trips through the sandbox.
|
|
34
|
-
*/
|
|
35
|
-
export declare function handleEgressRequest(request: Request, options: {
|
|
36
|
-
signingSecret: string;
|
|
37
|
-
resolveSecret: EgressSecretResolver;
|
|
38
|
-
fetchImpl?: typeof fetch;
|
|
39
|
-
now?: () => number;
|
|
40
|
-
}): Promise<Response>;
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
// src/drivers/cloudflare-egress.ts
|
|
2
|
-
function b64urlEncode(bytes) {
|
|
3
|
-
let binary = "";
|
|
4
|
-
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
5
|
-
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
6
|
-
}
|
|
7
|
-
function b64urlDecode(input) {
|
|
8
|
-
const padded = input.replace(/-/g, "+").replace(/_/g, "/") + "=".repeat((4 - input.length % 4) % 4);
|
|
9
|
-
const binary = atob(padded);
|
|
10
|
-
const bytes = new Uint8Array(binary.length);
|
|
11
|
-
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
12
|
-
return bytes;
|
|
13
|
-
}
|
|
14
|
-
function encodeJson(value) {
|
|
15
|
-
return b64urlEncode(new TextEncoder().encode(JSON.stringify(value)));
|
|
16
|
-
}
|
|
17
|
-
async function hmacKey(secret) {
|
|
18
|
-
return crypto.subtle.importKey(
|
|
19
|
-
"raw",
|
|
20
|
-
new TextEncoder().encode(secret),
|
|
21
|
-
{ name: "HMAC", hash: "SHA-256" },
|
|
22
|
-
false,
|
|
23
|
-
["sign", "verify"]
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
function timingSafeEqual(a, b) {
|
|
27
|
-
if (a.length !== b.length) return false;
|
|
28
|
-
let diff = 0;
|
|
29
|
-
for (let i = 0; i < a.length; i++) diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
30
|
-
return diff === 0;
|
|
31
|
-
}
|
|
32
|
-
async function mintEgressToken(input) {
|
|
33
|
-
const now = input.now ?? Date.now;
|
|
34
|
-
const header = encodeJson({ alg: "HS256", typ: "JWT" });
|
|
35
|
-
const payload = encodeJson({
|
|
36
|
-
sub: input.sandboxId,
|
|
37
|
-
hosts: input.hosts,
|
|
38
|
-
exp: Math.floor(now() / 1e3) + (input.ttlSeconds ?? 15 * 60)
|
|
39
|
-
});
|
|
40
|
-
const key = await hmacKey(input.signingSecret);
|
|
41
|
-
const sig = new Uint8Array(await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(`${header}.${payload}`)));
|
|
42
|
-
return `${header}.${payload}.${b64urlEncode(sig)}`;
|
|
43
|
-
}
|
|
44
|
-
async function verifyEgressToken(token, signingSecret, now = Date.now) {
|
|
45
|
-
const parts = token.split(".");
|
|
46
|
-
if (parts.length !== 3) return null;
|
|
47
|
-
const [header, payload, sig] = parts;
|
|
48
|
-
const key = await hmacKey(signingSecret);
|
|
49
|
-
const expected = b64urlEncode(
|
|
50
|
-
new Uint8Array(await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(`${header}.${payload}`)))
|
|
51
|
-
);
|
|
52
|
-
if (!timingSafeEqual(sig, expected)) return null;
|
|
53
|
-
let claims;
|
|
54
|
-
try {
|
|
55
|
-
claims = JSON.parse(new TextDecoder().decode(b64urlDecode(payload)));
|
|
56
|
-
} catch {
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
if (typeof claims.sub !== "string" || !Array.isArray(claims.hosts) || typeof claims.exp !== "number") return null;
|
|
60
|
-
if (claims.exp <= Math.floor(now() / 1e3)) return null;
|
|
61
|
-
return claims;
|
|
62
|
-
}
|
|
63
|
-
var EGRESS_TARGET_HEADER = "x-claxedo-egress-target";
|
|
64
|
-
async function handleEgressRequest(request, options) {
|
|
65
|
-
const fetchImpl = options.fetchImpl ?? fetch;
|
|
66
|
-
const auth = request.headers.get("authorization");
|
|
67
|
-
const token = auth?.toLowerCase().startsWith("bearer ") ? auth.slice(7) : void 0;
|
|
68
|
-
if (!token) return egressError(401, "missing egress token");
|
|
69
|
-
const claims = await verifyEgressToken(token, options.signingSecret, options.now);
|
|
70
|
-
if (!claims) return egressError(401, "invalid or expired egress token");
|
|
71
|
-
const targetRaw = request.headers.get(EGRESS_TARGET_HEADER);
|
|
72
|
-
if (!targetRaw) return egressError(400, "missing egress target");
|
|
73
|
-
let target;
|
|
74
|
-
try {
|
|
75
|
-
target = new URL(targetRaw);
|
|
76
|
-
} catch {
|
|
77
|
-
return egressError(400, "malformed egress target");
|
|
78
|
-
}
|
|
79
|
-
if (target.protocol !== "https:") return egressError(400, "egress target must be https");
|
|
80
|
-
if (!claims.hosts.includes(target.host)) return egressError(403, "host not permitted for this sandbox");
|
|
81
|
-
const secret = await options.resolveSecret(claims.sub, target.host);
|
|
82
|
-
if (!secret) return egressError(403, "no brokered credential for host");
|
|
83
|
-
const headers = new Headers(request.headers);
|
|
84
|
-
headers.delete("authorization");
|
|
85
|
-
headers.delete(EGRESS_TARGET_HEADER);
|
|
86
|
-
headers.set(secret.header, secret.value);
|
|
87
|
-
headers.set("host", target.host);
|
|
88
|
-
try {
|
|
89
|
-
const upstream = await fetchImpl(target.toString(), {
|
|
90
|
-
method: request.method,
|
|
91
|
-
headers,
|
|
92
|
-
body: request.method === "GET" || request.method === "HEAD" ? void 0 : request.body,
|
|
93
|
-
redirect: "manual"
|
|
94
|
-
});
|
|
95
|
-
const outHeaders = new Headers(upstream.headers);
|
|
96
|
-
outHeaders.delete(secret.header);
|
|
97
|
-
return new Response(upstream.body, { status: upstream.status, statusText: upstream.statusText, headers: outHeaders });
|
|
98
|
-
} catch {
|
|
99
|
-
return egressError(502, "upstream request failed");
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
function egressError(status, message) {
|
|
103
|
-
return new Response(JSON.stringify({ error: message }), {
|
|
104
|
-
status,
|
|
105
|
-
headers: { "content-type": "application/json" }
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
export {
|
|
109
|
-
EGRESS_TARGET_HEADER,
|
|
110
|
-
handleEgressRequest,
|
|
111
|
-
mintEgressToken,
|
|
112
|
-
verifyEgressToken
|
|
113
|
-
};
|