1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { getMainExport } from "https://esm.town/v/easrng/oldstyleUtil?v=1";
import { API_URL } from "https://esm.town/v/std/API_URL?v=5";
import { blob } from "https://esm.town/v/std/blob?v=11";
import { decodeBase64, encodeBase64 } from "jsr:@std/encoding@0.219.1/base64";
type SerializedRequest = {
headers: [string, string][];
method: string;
url: string;
body?: string;
};
type SerializedResponse = {
headers: [string, string][];
status: number;
statusText: string;
body: string;
};
export async function handle(req: Request) {
const id = new URL(req.url).hostname.match(/^websandbox-(play_[^\.]+)/)[1];
const code = await (await blob.get(id)).text();
const serializedRequest: SerializedRequest = {
headers: [],
method: req.method,
url: req.url,
body: (req.method === "GET" || req.method === "HEAD") ? undefined : encodeBase64(await req.arrayBuffer()),
};
req.headers.forEach((value, key) => {
serializedRequest.headers.push([key, value]);
});
const res = await fetch(API_URL + "/v1/eval", {
method: "POST",
body: JSON.stringify({
code: `async (serializedRequest, code) => JSON.stringify(await(await import(${
JSON.stringify(import.meta.url)
})).inner(serializedRequest, code))`,
args: [serializedRequest, code],
}),
});
const serializedResponse: SerializedResponse = await res.json();
return new Response(decodeBase64(serializedResponse.body), {
headers: serializedResponse.headers,
status: serializedResponse.status,
statusText: serializedResponse.statusText,
});
}
export async function inner(serializedRequest: SerializedRequest, code: string): Promise<SerializedResponse> {
try {
const req = new Request(serializedRequest.url, {
method: serializedRequest.method,
headers: serializedRequest.headers,
body: serializedRequest.body ? decodeBase64(serializedRequest.body) : undefined,
});
const blob = new Blob([code], {
type: "text/tsx",
});
const url = URL.createObjectURL(blob);
const handler = getMainExport(await import(url));
URL.revokeObjectURL(url);
const res: unknown = await handler(req);
if (!(res instanceof Response)) {
throw new TypeError(
"return type must be Response, got " + (typeof res === "object" ? Object.toString.call(res) : typeof res),
);
}
const serializedResponse: SerializedResponse = {
status: res.status,
statusText: res.statusText,
headers: [],
body: encodeBase64(await res.arrayBuffer()),
};
res.headers.forEach((value, key) => {
serializedResponse.headers.push([key, value]);
});
return serializedResponse;
} catch (e) {
return {
status: 500,
statusText: "Internal Server Error",
headers: [
["content-type", "text/plain"],
],
body: encodeBase64(e.stack),
};
}
}
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
March 9, 2024