@cloudflare/sandbox 0.3.6 → 0.4.1
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/.turbo/turbo-build.log +44 -0
- package/CHANGELOG.md +6 -8
- package/Dockerfile +88 -18
- package/README.md +89 -824
- package/dist/{chunk-JTKON2SH.js → chunk-BCJ7SF3Q.js} +9 -5
- package/dist/chunk-BCJ7SF3Q.js.map +1 -0
- package/dist/chunk-BFVUNTP4.js +104 -0
- package/dist/chunk-BFVUNTP4.js.map +1 -0
- package/dist/{chunk-NNGBXDMY.js → chunk-EKSWCBCA.js} +3 -6
- package/dist/chunk-EKSWCBCA.js.map +1 -0
- package/dist/chunk-HGF554LH.js +2236 -0
- package/dist/chunk-HGF554LH.js.map +1 -0
- package/dist/{chunk-6UAWTJ5S.js → chunk-Z532A7QC.js} +13 -20
- package/dist/{chunk-6UAWTJ5S.js.map → chunk-Z532A7QC.js.map} +1 -1
- package/dist/file-stream.d.ts +16 -38
- package/dist/file-stream.js +1 -2
- package/dist/index.d.ts +6 -5
- package/dist/index.js +35 -39
- package/dist/index.js.map +1 -1
- package/dist/interpreter.d.ts +3 -3
- package/dist/interpreter.js +2 -2
- package/dist/request-handler.d.ts +4 -3
- package/dist/request-handler.js +4 -7
- package/dist/sandbox-D9K2ypln.d.ts +583 -0
- package/dist/sandbox.d.ts +3 -3
- package/dist/sandbox.js +4 -7
- package/dist/security.d.ts +4 -3
- package/dist/security.js +3 -3
- package/dist/sse-parser.js +1 -1
- package/package.json +11 -5
- package/src/clients/base-client.ts +280 -0
- package/src/clients/command-client.ts +115 -0
- package/src/clients/file-client.ts +269 -0
- package/src/clients/git-client.ts +92 -0
- package/src/clients/index.ts +63 -0
- package/src/{interpreter-client.ts → clients/interpreter-client.ts} +148 -171
- package/src/clients/port-client.ts +105 -0
- package/src/clients/process-client.ts +177 -0
- package/src/clients/sandbox-client.ts +41 -0
- package/src/clients/types.ts +84 -0
- package/src/clients/utility-client.ts +94 -0
- package/src/errors/adapter.ts +180 -0
- package/src/errors/classes.ts +469 -0
- package/src/errors/index.ts +105 -0
- package/src/file-stream.ts +119 -117
- package/src/index.ts +81 -69
- package/src/interpreter.ts +17 -8
- package/src/request-handler.ts +69 -43
- package/src/sandbox.ts +694 -533
- package/src/security.ts +14 -23
- package/src/sse-parser.ts +4 -8
- package/startup.sh +3 -0
- package/tests/base-client.test.ts +328 -0
- package/tests/command-client.test.ts +407 -0
- package/tests/file-client.test.ts +643 -0
- package/tests/file-stream.test.ts +306 -0
- package/tests/git-client.test.ts +328 -0
- package/tests/port-client.test.ts +301 -0
- package/tests/process-client.test.ts +658 -0
- package/tests/sandbox.test.ts +465 -0
- package/tests/sse-parser.test.ts +290 -0
- package/tests/utility-client.test.ts +266 -0
- package/tests/wrangler.jsonc +35 -0
- package/tsconfig.json +9 -1
- package/vitest.config.ts +31 -0
- package/container_src/bun.lock +0 -76
- package/container_src/circuit-breaker.ts +0 -121
- package/container_src/control-process.ts +0 -784
- package/container_src/handler/exec.ts +0 -185
- package/container_src/handler/file.ts +0 -457
- package/container_src/handler/git.ts +0 -130
- package/container_src/handler/ports.ts +0 -314
- package/container_src/handler/process.ts +0 -568
- package/container_src/handler/session.ts +0 -92
- package/container_src/index.ts +0 -601
- package/container_src/interpreter-service.ts +0 -276
- package/container_src/isolation.ts +0 -1213
- package/container_src/mime-processor.ts +0 -255
- package/container_src/package.json +0 -18
- package/container_src/runtime/executors/javascript/node_executor.ts +0 -123
- package/container_src/runtime/executors/python/ipython_executor.py +0 -338
- package/container_src/runtime/executors/typescript/ts_executor.ts +0 -138
- package/container_src/runtime/process-pool.ts +0 -464
- package/container_src/shell-escape.ts +0 -42
- package/container_src/startup.sh +0 -11
- package/container_src/types.ts +0 -131
- package/dist/chunk-32UDXUPC.js +0 -671
- package/dist/chunk-32UDXUPC.js.map +0 -1
- package/dist/chunk-5DILEXGY.js +0 -85
- package/dist/chunk-5DILEXGY.js.map +0 -1
- package/dist/chunk-D3U63BZP.js +0 -240
- package/dist/chunk-D3U63BZP.js.map +0 -1
- package/dist/chunk-FXYPFGOZ.js +0 -129
- package/dist/chunk-FXYPFGOZ.js.map +0 -1
- package/dist/chunk-JTKON2SH.js.map +0 -1
- package/dist/chunk-NNGBXDMY.js.map +0 -1
- package/dist/chunk-SQLJNZ3K.js +0 -674
- package/dist/chunk-SQLJNZ3K.js.map +0 -1
- package/dist/chunk-W7TVRPBG.js +0 -108
- package/dist/chunk-W7TVRPBG.js.map +0 -1
- package/dist/client-B3RUab0s.d.ts +0 -225
- package/dist/client.d.ts +0 -4
- package/dist/client.js +0 -7
- package/dist/client.js.map +0 -1
- package/dist/errors.d.ts +0 -95
- package/dist/errors.js +0 -27
- package/dist/errors.js.map +0 -1
- package/dist/interpreter-client.d.ts +0 -4
- package/dist/interpreter-client.js +0 -9
- package/dist/interpreter-client.js.map +0 -1
- package/dist/interpreter-types.d.ts +0 -259
- package/dist/interpreter-types.js +0 -9
- package/dist/interpreter-types.js.map +0 -1
- package/dist/types.d.ts +0 -453
- package/dist/types.js +0 -45
- package/dist/types.js.map +0 -1
- package/src/client.ts +0 -1048
- package/src/errors.ts +0 -219
- package/src/interpreter-types.ts +0 -390
- package/src/types.ts +0 -571
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import { randomBytes } from "node:crypto";
|
|
2
|
-
import type { Session, SessionManager } from "../isolation";
|
|
3
|
-
import type { GitCheckoutRequest } from "../types";
|
|
4
|
-
|
|
5
|
-
async function executeGitCheckout(
|
|
6
|
-
sessionManager: SessionManager,
|
|
7
|
-
sessionId: string | undefined,
|
|
8
|
-
repoUrl: string,
|
|
9
|
-
branch: string,
|
|
10
|
-
targetDir: string
|
|
11
|
-
): Promise<{
|
|
12
|
-
success: boolean;
|
|
13
|
-
stdout: string;
|
|
14
|
-
stderr: string;
|
|
15
|
-
exitCode: number;
|
|
16
|
-
}> {
|
|
17
|
-
// Execute git clone through the session to respect working directory
|
|
18
|
-
const command = `git clone -b ${branch} ${repoUrl} ${targetDir}`;
|
|
19
|
-
|
|
20
|
-
// Use specific session if provided, otherwise use default session
|
|
21
|
-
let session: Session | undefined;
|
|
22
|
-
|
|
23
|
-
if (sessionId) {
|
|
24
|
-
session = sessionManager.getSession(sessionId);
|
|
25
|
-
if (!session) {
|
|
26
|
-
throw new Error(`Session '${sessionId}' not found`);
|
|
27
|
-
}
|
|
28
|
-
} else {
|
|
29
|
-
// Use the centralized method to get or create default session
|
|
30
|
-
session = await sessionManager.getOrCreateDefaultSession();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return session.exec(command);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export async function handleGitCheckoutRequest(
|
|
37
|
-
req: Request,
|
|
38
|
-
corsHeaders: Record<string, string>,
|
|
39
|
-
sessionManager: SessionManager
|
|
40
|
-
): Promise<Response> {
|
|
41
|
-
try {
|
|
42
|
-
const body = (await req.json()) as GitCheckoutRequest;
|
|
43
|
-
const { repoUrl, branch = "main", targetDir, sessionId } = body;
|
|
44
|
-
|
|
45
|
-
if (!repoUrl || typeof repoUrl !== "string") {
|
|
46
|
-
return new Response(
|
|
47
|
-
JSON.stringify({
|
|
48
|
-
error: "Repository URL is required and must be a string",
|
|
49
|
-
}),
|
|
50
|
-
{
|
|
51
|
-
headers: {
|
|
52
|
-
"Content-Type": "application/json",
|
|
53
|
-
...corsHeaders,
|
|
54
|
-
},
|
|
55
|
-
status: 400,
|
|
56
|
-
}
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Validate repository URL format
|
|
61
|
-
const urlPattern =
|
|
62
|
-
/^(https?:\/\/|git@|ssh:\/\/).*\.git$|^https?:\/\/.*\/.*$/;
|
|
63
|
-
if (!urlPattern.test(repoUrl)) {
|
|
64
|
-
return new Response(
|
|
65
|
-
JSON.stringify({
|
|
66
|
-
error: "Invalid repository URL format",
|
|
67
|
-
}),
|
|
68
|
-
{
|
|
69
|
-
headers: {
|
|
70
|
-
"Content-Type": "application/json",
|
|
71
|
-
...corsHeaders,
|
|
72
|
-
},
|
|
73
|
-
status: 400,
|
|
74
|
-
}
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Generate target directory if not provided using cryptographically secure randomness
|
|
79
|
-
const checkoutDir =
|
|
80
|
-
targetDir ||
|
|
81
|
-
`repo_${Date.now()}_${randomBytes(6).toString('hex')}`;
|
|
82
|
-
|
|
83
|
-
console.log(
|
|
84
|
-
`[Server] Checking out repository: ${repoUrl} to ${checkoutDir}${sessionId ? ` in session: ${sessionId}` : ''}`
|
|
85
|
-
);
|
|
86
|
-
|
|
87
|
-
const result = await executeGitCheckout(
|
|
88
|
-
sessionManager,
|
|
89
|
-
sessionId,
|
|
90
|
-
repoUrl,
|
|
91
|
-
branch,
|
|
92
|
-
checkoutDir
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
return new Response(
|
|
96
|
-
JSON.stringify({
|
|
97
|
-
branch,
|
|
98
|
-
exitCode: result.exitCode,
|
|
99
|
-
repoUrl,
|
|
100
|
-
stderr: result.stderr,
|
|
101
|
-
stdout: result.stdout,
|
|
102
|
-
success: result.success,
|
|
103
|
-
targetDir: checkoutDir,
|
|
104
|
-
timestamp: new Date().toISOString(),
|
|
105
|
-
}),
|
|
106
|
-
{
|
|
107
|
-
headers: {
|
|
108
|
-
"Content-Type": "application/json",
|
|
109
|
-
...corsHeaders,
|
|
110
|
-
},
|
|
111
|
-
}
|
|
112
|
-
);
|
|
113
|
-
} catch (error) {
|
|
114
|
-
console.error("[Server] Error in handleGitCheckoutRequest:", error);
|
|
115
|
-
return new Response(
|
|
116
|
-
JSON.stringify({
|
|
117
|
-
error: "Failed to checkout repository",
|
|
118
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
119
|
-
}),
|
|
120
|
-
{
|
|
121
|
-
headers: {
|
|
122
|
-
"Content-Type": "application/json",
|
|
123
|
-
...corsHeaders,
|
|
124
|
-
},
|
|
125
|
-
status: 500,
|
|
126
|
-
}
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
import type { ExposePortRequest, UnexposePortRequest } from "../types";
|
|
2
|
-
|
|
3
|
-
export async function handleExposePortRequest(
|
|
4
|
-
exposedPorts: Map<number, { name?: string; exposedAt: Date }>,
|
|
5
|
-
req: Request,
|
|
6
|
-
corsHeaders: Record<string, string>
|
|
7
|
-
): Promise<Response> {
|
|
8
|
-
try {
|
|
9
|
-
const body = (await req.json()) as ExposePortRequest;
|
|
10
|
-
const { port, name } = body;
|
|
11
|
-
|
|
12
|
-
if (!port || typeof port !== "number") {
|
|
13
|
-
return new Response(
|
|
14
|
-
JSON.stringify({
|
|
15
|
-
error: "Port is required and must be a number",
|
|
16
|
-
}),
|
|
17
|
-
{
|
|
18
|
-
headers: {
|
|
19
|
-
"Content-Type": "application/json",
|
|
20
|
-
...corsHeaders,
|
|
21
|
-
},
|
|
22
|
-
status: 400,
|
|
23
|
-
}
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Validate port range
|
|
28
|
-
if (port < 1 || port > 65535) {
|
|
29
|
-
return new Response(
|
|
30
|
-
JSON.stringify({
|
|
31
|
-
error: "Port must be between 1 and 65535",
|
|
32
|
-
}),
|
|
33
|
-
{
|
|
34
|
-
headers: {
|
|
35
|
-
"Content-Type": "application/json",
|
|
36
|
-
...corsHeaders,
|
|
37
|
-
},
|
|
38
|
-
status: 400,
|
|
39
|
-
}
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Store the exposed port
|
|
44
|
-
exposedPorts.set(port, { name, exposedAt: new Date() });
|
|
45
|
-
|
|
46
|
-
console.log(`[Server] Exposed port: ${port}${name ? ` (${name})` : ""}`);
|
|
47
|
-
|
|
48
|
-
return new Response(
|
|
49
|
-
JSON.stringify({
|
|
50
|
-
port,
|
|
51
|
-
name,
|
|
52
|
-
exposedAt: new Date().toISOString(),
|
|
53
|
-
success: true,
|
|
54
|
-
timestamp: new Date().toISOString(),
|
|
55
|
-
}),
|
|
56
|
-
{
|
|
57
|
-
headers: {
|
|
58
|
-
"Content-Type": "application/json",
|
|
59
|
-
...corsHeaders,
|
|
60
|
-
},
|
|
61
|
-
}
|
|
62
|
-
);
|
|
63
|
-
} catch (error) {
|
|
64
|
-
console.error("[Server] Error in handleExposePortRequest:", error);
|
|
65
|
-
return new Response(
|
|
66
|
-
JSON.stringify({
|
|
67
|
-
error: "Failed to expose port",
|
|
68
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
69
|
-
}),
|
|
70
|
-
{
|
|
71
|
-
headers: {
|
|
72
|
-
"Content-Type": "application/json",
|
|
73
|
-
...corsHeaders,
|
|
74
|
-
},
|
|
75
|
-
status: 500,
|
|
76
|
-
}
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export async function handleUnexposePortRequest(
|
|
82
|
-
exposedPorts: Map<number, { name?: string; exposedAt: Date }>,
|
|
83
|
-
req: Request,
|
|
84
|
-
corsHeaders: Record<string, string>
|
|
85
|
-
): Promise<Response> {
|
|
86
|
-
try {
|
|
87
|
-
const body = (await req.json()) as UnexposePortRequest;
|
|
88
|
-
const { port } = body;
|
|
89
|
-
|
|
90
|
-
if (!port || typeof port !== "number") {
|
|
91
|
-
return new Response(
|
|
92
|
-
JSON.stringify({
|
|
93
|
-
error: "Port is required and must be a number",
|
|
94
|
-
}),
|
|
95
|
-
{
|
|
96
|
-
headers: {
|
|
97
|
-
"Content-Type": "application/json",
|
|
98
|
-
...corsHeaders,
|
|
99
|
-
},
|
|
100
|
-
status: 400,
|
|
101
|
-
}
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Check if port is exposed
|
|
106
|
-
if (!exposedPorts.has(port)) {
|
|
107
|
-
return new Response(
|
|
108
|
-
JSON.stringify({
|
|
109
|
-
error: "Port is not exposed",
|
|
110
|
-
}),
|
|
111
|
-
{
|
|
112
|
-
headers: {
|
|
113
|
-
"Content-Type": "application/json",
|
|
114
|
-
...corsHeaders,
|
|
115
|
-
},
|
|
116
|
-
status: 404,
|
|
117
|
-
}
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Remove the exposed port
|
|
122
|
-
exposedPorts.delete(port);
|
|
123
|
-
|
|
124
|
-
console.log(`[Server] Unexposed port: ${port}`);
|
|
125
|
-
|
|
126
|
-
return new Response(
|
|
127
|
-
JSON.stringify({
|
|
128
|
-
port,
|
|
129
|
-
success: true,
|
|
130
|
-
timestamp: new Date().toISOString(),
|
|
131
|
-
}),
|
|
132
|
-
{
|
|
133
|
-
headers: {
|
|
134
|
-
"Content-Type": "application/json",
|
|
135
|
-
...corsHeaders,
|
|
136
|
-
},
|
|
137
|
-
}
|
|
138
|
-
);
|
|
139
|
-
} catch (error) {
|
|
140
|
-
console.error("[Server] Error in handleUnexposePortRequest:", error);
|
|
141
|
-
return new Response(
|
|
142
|
-
JSON.stringify({
|
|
143
|
-
error: "Failed to unexpose port",
|
|
144
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
145
|
-
}),
|
|
146
|
-
{
|
|
147
|
-
headers: {
|
|
148
|
-
"Content-Type": "application/json",
|
|
149
|
-
...corsHeaders,
|
|
150
|
-
},
|
|
151
|
-
status: 500,
|
|
152
|
-
}
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export async function handleGetExposedPortsRequest(
|
|
158
|
-
exposedPorts: Map<number, { name?: string; exposedAt: Date }>,
|
|
159
|
-
req: Request,
|
|
160
|
-
corsHeaders: Record<string, string>
|
|
161
|
-
): Promise<Response> {
|
|
162
|
-
try {
|
|
163
|
-
const ports = Array.from(exposedPorts.entries()).map(([port, info]) => ({
|
|
164
|
-
port,
|
|
165
|
-
name: info.name,
|
|
166
|
-
exposedAt: info.exposedAt.toISOString(),
|
|
167
|
-
}));
|
|
168
|
-
|
|
169
|
-
return new Response(
|
|
170
|
-
JSON.stringify({
|
|
171
|
-
ports,
|
|
172
|
-
count: ports.length,
|
|
173
|
-
timestamp: new Date().toISOString(),
|
|
174
|
-
}),
|
|
175
|
-
{
|
|
176
|
-
headers: {
|
|
177
|
-
"Content-Type": "application/json",
|
|
178
|
-
...corsHeaders,
|
|
179
|
-
},
|
|
180
|
-
}
|
|
181
|
-
);
|
|
182
|
-
} catch (error) {
|
|
183
|
-
console.error("[Server] Error in handleGetExposedPortsRequest:", error);
|
|
184
|
-
return new Response(
|
|
185
|
-
JSON.stringify({
|
|
186
|
-
error: "Failed to get exposed ports",
|
|
187
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
188
|
-
}),
|
|
189
|
-
{
|
|
190
|
-
headers: {
|
|
191
|
-
"Content-Type": "application/json",
|
|
192
|
-
...corsHeaders,
|
|
193
|
-
},
|
|
194
|
-
status: 500,
|
|
195
|
-
}
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
export async function handleProxyRequest(
|
|
201
|
-
exposedPorts: Map<number, { name?: string; exposedAt: Date }>,
|
|
202
|
-
req: Request,
|
|
203
|
-
corsHeaders: Record<string, string>
|
|
204
|
-
): Promise<Response> {
|
|
205
|
-
try {
|
|
206
|
-
const url = new URL(req.url);
|
|
207
|
-
const pathParts = url.pathname.split("/");
|
|
208
|
-
|
|
209
|
-
// Extract port from path like /proxy/3000/...
|
|
210
|
-
if (pathParts.length < 3) {
|
|
211
|
-
return new Response(
|
|
212
|
-
JSON.stringify({
|
|
213
|
-
error: "Invalid proxy path",
|
|
214
|
-
}),
|
|
215
|
-
{
|
|
216
|
-
headers: {
|
|
217
|
-
"Content-Type": "application/json",
|
|
218
|
-
...corsHeaders,
|
|
219
|
-
},
|
|
220
|
-
status: 400,
|
|
221
|
-
}
|
|
222
|
-
);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const port = parseInt(pathParts[2]);
|
|
226
|
-
if (!port || Number.isNaN(port)) {
|
|
227
|
-
return new Response(
|
|
228
|
-
JSON.stringify({
|
|
229
|
-
error: "Invalid port in proxy path",
|
|
230
|
-
}),
|
|
231
|
-
{
|
|
232
|
-
headers: {
|
|
233
|
-
"Content-Type": "application/json",
|
|
234
|
-
...corsHeaders,
|
|
235
|
-
},
|
|
236
|
-
status: 400,
|
|
237
|
-
}
|
|
238
|
-
);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Check if port is exposed
|
|
242
|
-
if (!exposedPorts.has(port)) {
|
|
243
|
-
return new Response(
|
|
244
|
-
JSON.stringify({
|
|
245
|
-
error: `Port ${port} is not exposed`,
|
|
246
|
-
}),
|
|
247
|
-
{
|
|
248
|
-
headers: {
|
|
249
|
-
"Content-Type": "application/json",
|
|
250
|
-
...corsHeaders,
|
|
251
|
-
},
|
|
252
|
-
status: 404,
|
|
253
|
-
}
|
|
254
|
-
);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// Construct the target URL
|
|
258
|
-
const targetPath = `/${pathParts.slice(3).join("/")}`;
|
|
259
|
-
// Use 127.0.0.1 instead of localhost for more reliable container networking
|
|
260
|
-
const targetUrl = `http://127.0.0.1:${port}${targetPath}${url.search}`;
|
|
261
|
-
|
|
262
|
-
console.log(`[Server] Proxying request to: ${targetUrl}`);
|
|
263
|
-
console.log(`[Server] Method: ${req.method}, Port: ${port}, Path: ${targetPath}`);
|
|
264
|
-
|
|
265
|
-
try {
|
|
266
|
-
// Forward the request to the target port
|
|
267
|
-
const targetResponse = await fetch(targetUrl, {
|
|
268
|
-
method: req.method,
|
|
269
|
-
headers: req.headers,
|
|
270
|
-
body: req.body,
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
// Return the response from the target
|
|
274
|
-
return new Response(targetResponse.body, {
|
|
275
|
-
status: targetResponse.status,
|
|
276
|
-
statusText: targetResponse.statusText,
|
|
277
|
-
headers: {
|
|
278
|
-
...Object.fromEntries(targetResponse.headers.entries()),
|
|
279
|
-
...corsHeaders,
|
|
280
|
-
},
|
|
281
|
-
});
|
|
282
|
-
} catch (fetchError) {
|
|
283
|
-
console.error(`[Server] Error proxying to port ${port}:`, fetchError);
|
|
284
|
-
return new Response(
|
|
285
|
-
JSON.stringify({
|
|
286
|
-
error: `Service on port ${port} is not responding`,
|
|
287
|
-
message: fetchError instanceof Error ? fetchError.message : "Unknown error",
|
|
288
|
-
}),
|
|
289
|
-
{
|
|
290
|
-
headers: {
|
|
291
|
-
"Content-Type": "application/json",
|
|
292
|
-
...corsHeaders,
|
|
293
|
-
},
|
|
294
|
-
status: 502,
|
|
295
|
-
}
|
|
296
|
-
);
|
|
297
|
-
}
|
|
298
|
-
} catch (error) {
|
|
299
|
-
console.error("[Server] Error in handleProxyRequest:", error);
|
|
300
|
-
return new Response(
|
|
301
|
-
JSON.stringify({
|
|
302
|
-
error: "Failed to proxy request",
|
|
303
|
-
message: error instanceof Error ? error.message : "Unknown error",
|
|
304
|
-
}),
|
|
305
|
-
{
|
|
306
|
-
headers: {
|
|
307
|
-
"Content-Type": "application/json",
|
|
308
|
-
...corsHeaders,
|
|
309
|
-
},
|
|
310
|
-
status: 500,
|
|
311
|
-
}
|
|
312
|
-
);
|
|
313
|
-
}
|
|
314
|
-
}
|