@openclaw/crabline 0.1.9 → 0.1.10
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 +47 -22
- package/assets/crabline-banner.svg +20 -0
- package/dist/src/bin/crabline.js.map +1 -1
- package/dist/src/cli/program.d.ts +25 -1
- package/dist/src/cli/program.js +579 -82
- package/dist/src/cli/program.js.map +1 -1
- package/dist/src/config/load.js +59 -6
- package/dist/src/config/load.js.map +1 -1
- package/dist/src/config/schema.d.ts +116 -92
- package/dist/src/config/schema.js +179 -73
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/core/errors.js +9 -2
- package/dist/src/core/errors.js.map +1 -1
- package/dist/src/core/exit-codes.js.map +1 -1
- package/dist/src/core/matcher.js +7 -6
- package/dist/src/core/matcher.js.map +1 -1
- package/dist/src/core/message-template.js.map +1 -1
- package/dist/src/core/nonces.d.ts +1 -0
- package/dist/src/core/nonces.js +4 -2
- package/dist/src/core/nonces.js.map +1 -1
- package/dist/src/core/reporters.d.ts +1 -0
- package/dist/src/core/reporters.js +42 -4
- package/dist/src/core/reporters.js.map +1 -1
- package/dist/src/core/run.d.ts +3 -0
- package/dist/src/core/run.js +415 -107
- package/dist/src/core/run.js.map +1 -1
- package/dist/src/core/safe-regex.d.ts +3 -0
- package/dist/src/core/safe-regex.js +21 -0
- package/dist/src/core/safe-regex.js.map +1 -0
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.js +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/openclaw/artifact-generation.d.ts +38 -0
- package/dist/src/openclaw/artifact-generation.js +314 -0
- package/dist/src/openclaw/artifact-generation.js.map +1 -0
- package/dist/src/openclaw/bridges/matrix.js +97 -12
- package/dist/src/openclaw/bridges/matrix.js.map +1 -1
- package/dist/src/openclaw/bridges/mattermost.js +32 -10
- package/dist/src/openclaw/bridges/mattermost.js.map +1 -1
- package/dist/src/openclaw/bridges/signal.js +55 -18
- package/dist/src/openclaw/bridges/signal.js.map +1 -1
- package/dist/src/openclaw/bridges/slack.js +85 -7
- package/dist/src/openclaw/bridges/slack.js.map +1 -1
- package/dist/src/openclaw/bridges/telegram.js +124 -30
- package/dist/src/openclaw/bridges/telegram.js.map +1 -1
- package/dist/src/openclaw/bridges/whatsapp.js +78 -17
- package/dist/src/openclaw/bridges/whatsapp.js.map +1 -1
- package/dist/src/openclaw/bridges/zalo.js +14 -5
- package/dist/src/openclaw/bridges/zalo.js.map +1 -1
- package/dist/src/openclaw/outbound-contract.d.ts +5 -0
- package/dist/src/openclaw/outbound-contract.js +40 -0
- package/dist/src/openclaw/outbound-contract.js.map +1 -0
- package/dist/src/openclaw/private-file.d.ts +26 -0
- package/dist/src/openclaw/private-file.js +411 -0
- package/dist/src/openclaw/private-file.js.map +1 -0
- package/dist/src/openclaw/shared.d.ts +21 -2
- package/dist/src/openclaw/shared.js +115 -18
- package/dist/src/openclaw/shared.js.map +1 -1
- package/dist/src/openclaw/smoke-lock.d.ts +63 -0
- package/dist/src/openclaw/smoke-lock.js +949 -0
- package/dist/src/openclaw/smoke-lock.js.map +1 -0
- package/dist/src/openclaw.d.ts +16 -8
- package/dist/src/openclaw.js +194 -52
- package/dist/src/openclaw.js.map +1 -1
- package/dist/src/providers/builtin/discord.d.ts +10 -1
- package/dist/src/providers/builtin/discord.js +144 -18
- package/dist/src/providers/builtin/discord.js.map +1 -1
- package/dist/src/providers/builtin/external-webhook-auth.d.ts +11 -0
- package/dist/src/providers/builtin/external-webhook-auth.js +10 -0
- package/dist/src/providers/builtin/external-webhook-auth.js.map +1 -0
- package/dist/src/providers/builtin/feishu.d.ts +19 -2
- package/dist/src/providers/builtin/feishu.js +307 -25
- package/dist/src/providers/builtin/feishu.js.map +1 -1
- package/dist/src/providers/builtin/googlechat.d.ts +20 -1
- package/dist/src/providers/builtin/googlechat.js +178 -19
- package/dist/src/providers/builtin/googlechat.js.map +1 -1
- package/dist/src/providers/builtin/imessage.d.ts +4 -0
- package/dist/src/providers/builtin/imessage.js +26 -11
- package/dist/src/providers/builtin/imessage.js.map +1 -1
- package/dist/src/providers/builtin/loopback.js +92 -30
- package/dist/src/providers/builtin/loopback.js.map +1 -1
- package/dist/src/providers/builtin/matrix.d.ts +11 -1
- package/dist/src/providers/builtin/matrix.js +53 -29
- package/dist/src/providers/builtin/matrix.js.map +1 -1
- package/dist/src/providers/builtin/mattermost.d.ts +10 -0
- package/dist/src/providers/builtin/mattermost.js +38 -15
- package/dist/src/providers/builtin/mattermost.js.map +1 -1
- package/dist/src/providers/builtin/msteams.d.ts +17 -1
- package/dist/src/providers/builtin/msteams.js +113 -14
- package/dist/src/providers/builtin/msteams.js.map +1 -1
- package/dist/src/providers/builtin/native-local-mock.d.ts +2 -9
- package/dist/src/providers/builtin/native-local-mock.js +12 -35
- package/dist/src/providers/builtin/native-local-mock.js.map +1 -1
- package/dist/src/providers/builtin/script.d.ts +11 -15
- package/dist/src/providers/builtin/script.js +566 -104
- package/dist/src/providers/builtin/script.js.map +1 -1
- package/dist/src/providers/builtin/slack.d.ts +6 -0
- package/dist/src/providers/builtin/slack.js +99 -40
- package/dist/src/providers/builtin/slack.js.map +1 -1
- package/dist/src/providers/builtin/telegram.d.ts +6 -0
- package/dist/src/providers/builtin/telegram.js +64 -43
- package/dist/src/providers/builtin/telegram.js.map +1 -1
- package/dist/src/providers/builtin/whatsapp.d.ts +28 -8
- package/dist/src/providers/builtin/whatsapp.js +567 -30
- package/dist/src/providers/builtin/whatsapp.js.map +1 -1
- package/dist/src/providers/builtin/zalo.js +30 -19
- package/dist/src/providers/builtin/zalo.js.map +1 -1
- package/dist/src/providers/catalog.d.ts +3 -3
- package/dist/src/providers/catalog.js +3 -3
- package/dist/src/providers/catalog.js.map +1 -1
- package/dist/src/providers/local-mock.d.ts +11 -2
- package/dist/src/providers/local-mock.js +322 -96
- package/dist/src/providers/local-mock.js.map +1 -1
- package/dist/src/providers/native-ids.d.ts +1 -0
- package/dist/src/providers/native-ids.js +6 -1
- package/dist/src/providers/native-ids.js.map +1 -1
- package/dist/src/providers/recorder.d.ts +30 -2
- package/dist/src/providers/recorder.js +539 -70
- package/dist/src/providers/recorder.js.map +1 -1
- package/dist/src/providers/registry.d.ts +25 -1
- package/dist/src/providers/registry.js +280 -40
- package/dist/src/providers/registry.js.map +1 -1
- package/dist/src/providers/signed-jwt.d.ts +29 -0
- package/dist/src/providers/signed-jwt.js +202 -0
- package/dist/src/providers/signed-jwt.js.map +1 -0
- package/dist/src/providers/slack-ids.js.map +1 -1
- package/dist/src/providers/target-normalizers.d.ts +26 -0
- package/dist/src/providers/target-normalizers.js +276 -0
- package/dist/src/providers/target-normalizers.js.map +1 -0
- package/dist/src/providers/types.d.ts +5 -0
- package/dist/src/providers/types.js.map +1 -1
- package/dist/src/providers/webhook-server.d.ts +2 -0
- package/dist/src/providers/webhook-server.js +72 -25
- package/dist/src/providers/webhook-server.js.map +1 -1
- package/dist/src/servers/http.d.ts +23 -3
- package/dist/src/servers/http.js +213 -20
- package/dist/src/servers/http.js.map +1 -1
- package/dist/src/servers/index.js +20 -21
- package/dist/src/servers/index.js.map +1 -1
- package/dist/src/servers/matrix.js +465 -51
- package/dist/src/servers/matrix.js.map +1 -1
- package/dist/src/servers/mattermost.d.ts +5 -0
- package/dist/src/servers/mattermost.js +306 -58
- package/dist/src/servers/mattermost.js.map +1 -1
- package/dist/src/servers/pending-events.d.ts +2 -0
- package/dist/src/servers/pending-events.js +11 -0
- package/dist/src/servers/pending-events.js.map +1 -0
- package/dist/src/servers/recorder.d.ts +5 -0
- package/dist/src/servers/recorder.js +46 -3
- package/dist/src/servers/recorder.js.map +1 -1
- package/dist/src/servers/signal.d.ts +2 -0
- package/dist/src/servers/signal.js +444 -56
- package/dist/src/servers/signal.js.map +1 -1
- package/dist/src/servers/slack.d.ts +5 -0
- package/dist/src/servers/slack.js +515 -49
- package/dist/src/servers/slack.js.map +1 -1
- package/dist/src/servers/telegram.d.ts +111 -0
- package/dist/src/servers/telegram.js +811 -152
- package/dist/src/servers/telegram.js.map +1 -1
- package/dist/src/servers/webhook-target.d.ts +40 -0
- package/dist/src/servers/webhook-target.js +349 -0
- package/dist/src/servers/webhook-target.js.map +1 -0
- package/dist/src/servers/websocket.d.ts +2 -0
- package/dist/src/servers/websocket.js +29 -0
- package/dist/src/servers/websocket.js.map +1 -0
- package/dist/src/servers/whatsapp-baileys-websocket.d.ts +65 -1
- package/dist/src/servers/whatsapp-baileys-websocket.js +723 -99
- package/dist/src/servers/whatsapp-baileys-websocket.js.map +1 -1
- package/dist/src/servers/whatsapp-jid.d.ts +5 -0
- package/dist/src/servers/whatsapp-jid.js +32 -0
- package/dist/src/servers/whatsapp-jid.js.map +1 -0
- package/dist/src/servers/whatsapp-wire/binary-node.d.ts +5 -0
- package/dist/src/servers/whatsapp-wire/binary-node.js +87 -20
- package/dist/src/servers/whatsapp-wire/binary-node.js.map +1 -1
- package/dist/src/servers/whatsapp-wire/crypto.d.ts +6 -1
- package/dist/src/servers/whatsapp-wire/crypto.js +99 -45
- package/dist/src/servers/whatsapp-wire/crypto.js.map +1 -1
- package/dist/src/servers/whatsapp-wire/handshake.js +39 -4
- package/dist/src/servers/whatsapp-wire/handshake.js.map +1 -1
- package/dist/src/servers/whatsapp-wire/signal.js.map +1 -1
- package/dist/src/servers/whatsapp.d.ts +12 -7
- package/dist/src/servers/whatsapp.js +269 -107
- package/dist/src/servers/whatsapp.js.map +1 -1
- package/dist/src/servers/zalo.d.ts +14 -0
- package/dist/src/servers/zalo.js +521 -88
- package/dist/src/servers/zalo.js.map +1 -1
- package/docs/channel-setup.md +197 -19
- package/fixtures/examples/crabline.example.yaml +10 -0
- package/package.json +20 -15
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/providers/types.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/providers/types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n FixtureDefinition,\n FixtureMode,\n InboundAuthor,\n ProviderConfig,\n ProviderPlatform,\n} from \"../config/schema.js\";\n\nexport type ProviderSupportStatus = \"bridge\" | \"planned\" | \"ready\";\n\nexport type InboundMatchConfig = {\n author: InboundAuthor;\n nonce: \"contains\" | \"exact\" | \"ignore\";\n pattern?: string | undefined;\n strategy: \"contains\" | \"exact\" | \"regex\";\n};\n\nexport type NormalizedTarget = {\n channelId?: string | undefined;\n id: string;\n metadata: Record<string, string>;\n threadId?: string | undefined;\n};\n\nexport type InboundEnvelope = {\n author: Exclude<InboundAuthor, \"any\">;\n id: string;\n provider: string;\n raw?: unknown;\n sentAt: string;\n text: string;\n threadId: string;\n};\n\nexport type ProbeResult = {\n details: string[];\n healthy: boolean;\n};\n\nexport type SendResult = {\n accepted: boolean;\n messageId: string;\n threadId: string;\n};\n\nexport type ProviderContext = {\n config: ProviderConfig;\n fixture: FixtureDefinition;\n manifestPath: string;\n providerId: string;\n signal?: AbortSignal | undefined;\n userName: string;\n};\n\nexport type SendContext = ProviderContext & {\n mode: Extract<FixtureMode, \"agent\" | \"roundtrip\" | \"send\">;\n nonce: string;\n text: string;\n};\n\nexport type WaitContext = ProviderContext & {\n excludeIds?: readonly string[] | undefined;\n nonce: string;\n since: string;\n threadId?: string | undefined;\n timeoutMs: number;\n};\n\nexport type WatchContext = ProviderContext & {\n signal?: AbortSignal | undefined;\n since?: string;\n};\n\nexport interface ProviderAdapter {\n readonly id: string;\n readonly platform: ProviderPlatform;\n readonly status: ProviderSupportStatus;\n readonly supports: readonly FixtureMode[];\n normalizeTarget(target: FixtureDefinition[\"target\"]): NormalizedTarget;\n probe(context: ProviderContext): Promise<ProbeResult>;\n send(context: SendContext): Promise<SendResult>;\n waitForInbound(context: WaitContext): Promise<InboundEnvelope | null>;\n watch?(context: WatchContext): AsyncIterable<InboundEnvelope>;\n /** Stops external admission synchronously before cleanup drains accepted work. */\n beginCleanup?(): void;\n cleanup?(): Promise<void>;\n}\n\nexport type LoopbackMessage = {\n author: {\n isMe: boolean;\n userName: string;\n };\n formatted: string;\n id: string;\n metadata: {\n dateSent: Date;\n edited: boolean;\n editedAt?: Date;\n };\n raw: {\n author: \"assistant\" | \"user\";\n id: string;\n text: string;\n threadId: string;\n timestamp: string;\n };\n text: string;\n threadId: string;\n};\n\nexport type LoopbackRawMessage = {\n author: \"assistant\" | \"user\";\n id: string;\n text: string;\n threadId: string;\n timestamp: string;\n};\n"]}
|
|
@@ -4,9 +4,11 @@ export type StartedWebhookServer = {
|
|
|
4
4
|
};
|
|
5
5
|
export declare function startWebhookServer(params: {
|
|
6
6
|
handle(request: Request): Promise<Response>;
|
|
7
|
+
bodyTimeoutMs?: number | undefined;
|
|
7
8
|
host: string;
|
|
8
9
|
maxBodyBytes?: number;
|
|
9
10
|
methods?: readonly string[] | undefined;
|
|
11
|
+
onError?: ((error: unknown) => void) | undefined;
|
|
10
12
|
path: string;
|
|
11
13
|
port: number;
|
|
12
14
|
}): Promise<StartedWebhookServer>;
|
|
@@ -1,48 +1,69 @@
|
|
|
1
1
|
import { createServer } from "node:http";
|
|
2
2
|
const DEFAULT_MAX_BODY_BYTES = 1024 * 1024;
|
|
3
|
+
const DEFAULT_BODY_TIMEOUT_MS = 5_000;
|
|
3
4
|
class RequestBodyTooLargeError extends Error {
|
|
4
5
|
}
|
|
5
|
-
|
|
6
|
+
class RequestBodyTimeoutError extends Error {
|
|
7
|
+
}
|
|
8
|
+
async function readRequestBody(request, maxBodyBytes, bodyTimeoutMs) {
|
|
6
9
|
return await new Promise((resolve, reject) => {
|
|
7
10
|
const chunks = [];
|
|
8
11
|
let bodyBytes = 0;
|
|
9
12
|
let settled = false;
|
|
10
|
-
|
|
13
|
+
const cleanup = (preserveErrorListener = false) => {
|
|
14
|
+
clearTimeout(timeout);
|
|
15
|
+
request.off("data", onData);
|
|
16
|
+
request.off("end", onEnd);
|
|
17
|
+
if (!preserveErrorListener) {
|
|
18
|
+
request.off("error", onError);
|
|
19
|
+
}
|
|
20
|
+
request.off("aborted", onAborted);
|
|
21
|
+
};
|
|
22
|
+
const fail = (error) => {
|
|
23
|
+
if (settled) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
settled = true;
|
|
27
|
+
cleanup(true);
|
|
28
|
+
reject(error);
|
|
29
|
+
};
|
|
30
|
+
const onData = (chunk) => {
|
|
11
31
|
if (settled) {
|
|
12
32
|
return;
|
|
13
33
|
}
|
|
14
34
|
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
15
35
|
bodyBytes += buffer.length;
|
|
16
36
|
if (bodyBytes > maxBodyBytes) {
|
|
17
|
-
settled = true;
|
|
18
37
|
request.resume();
|
|
19
|
-
|
|
38
|
+
fail(new RequestBodyTooLargeError());
|
|
20
39
|
return;
|
|
21
40
|
}
|
|
22
41
|
chunks.push(buffer);
|
|
23
|
-
}
|
|
24
|
-
|
|
42
|
+
};
|
|
43
|
+
const onEnd = () => {
|
|
25
44
|
if (settled) {
|
|
26
45
|
return;
|
|
27
46
|
}
|
|
28
47
|
settled = true;
|
|
48
|
+
cleanup();
|
|
29
49
|
resolve(Buffer.concat(chunks));
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
50
|
+
};
|
|
51
|
+
const onError = (error) => fail(error);
|
|
52
|
+
const onAborted = () => fail(new Error("request body aborted"));
|
|
53
|
+
const timeout = setTimeout(() => {
|
|
54
|
+
request.resume();
|
|
55
|
+
fail(new RequestBodyTimeoutError());
|
|
56
|
+
}, bodyTimeoutMs);
|
|
57
|
+
request.on("data", onData);
|
|
58
|
+
request.once("end", onEnd);
|
|
59
|
+
request.once("error", onError);
|
|
60
|
+
request.once("aborted", onAborted);
|
|
38
61
|
});
|
|
39
62
|
}
|
|
40
|
-
async function toFetchRequest(request, maxBodyBytes) {
|
|
41
|
-
const host = request.headers.host ?? "127.0.0.1";
|
|
42
|
-
const url = new URL(request.url ?? "/", `http://${host}`);
|
|
63
|
+
async function toFetchRequest(request, url, maxBodyBytes, bodyTimeoutMs) {
|
|
43
64
|
const body = request.method === "GET" || request.method === "HEAD"
|
|
44
65
|
? undefined
|
|
45
|
-
: await readRequestBody(request, maxBodyBytes);
|
|
66
|
+
: await readRequestBody(request, maxBodyBytes, bodyTimeoutMs);
|
|
46
67
|
const init = {
|
|
47
68
|
headers: request.headers,
|
|
48
69
|
};
|
|
@@ -76,25 +97,51 @@ function closeServer(server) {
|
|
|
76
97
|
}
|
|
77
98
|
resolve();
|
|
78
99
|
});
|
|
100
|
+
server.closeAllConnections();
|
|
79
101
|
});
|
|
80
102
|
}
|
|
103
|
+
function formatUrlHost(host) {
|
|
104
|
+
return host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
|
|
105
|
+
}
|
|
81
106
|
export async function startWebhookServer(params) {
|
|
82
107
|
const methods = new Set(params.methods ?? ["POST"]);
|
|
83
108
|
const maxBodyBytes = params.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;
|
|
109
|
+
const bodyTimeoutMs = params.bodyTimeoutMs ?? DEFAULT_BODY_TIMEOUT_MS;
|
|
84
110
|
const server = createServer(async (request, response) => {
|
|
85
111
|
try {
|
|
86
|
-
const
|
|
87
|
-
const
|
|
88
|
-
|
|
112
|
+
const method = request.method ?? "GET";
|
|
113
|
+
const host = request.headers.host ?? "127.0.0.1";
|
|
114
|
+
const url = new URL(request.url ?? "/", `http://${host}`);
|
|
115
|
+
if (!methods.has(method) || url.pathname !== params.path) {
|
|
116
|
+
request.resume();
|
|
89
117
|
await writeFetchResponse(response, new Response("not found", { status: 404 }));
|
|
90
118
|
return;
|
|
91
119
|
}
|
|
120
|
+
const fetchRequest = await toFetchRequest(request, url, maxBodyBytes, bodyTimeoutMs);
|
|
92
121
|
await writeFetchResponse(response, await params.handle(fetchRequest));
|
|
93
122
|
}
|
|
94
123
|
catch (error) {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
124
|
+
const status = error instanceof RequestBodyTooLargeError
|
|
125
|
+
? 413
|
|
126
|
+
: error instanceof RequestBodyTimeoutError
|
|
127
|
+
? 408
|
|
128
|
+
: 500;
|
|
129
|
+
if (status === 500) {
|
|
130
|
+
try {
|
|
131
|
+
params.onError?.(error);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Error reporting must not change the public response.
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
await writeFetchResponse(response, new Response(status === 413
|
|
138
|
+
? "request body too large"
|
|
139
|
+
: status === 408
|
|
140
|
+
? "request body timeout"
|
|
141
|
+
: "internal server error", {
|
|
142
|
+
...(status === 408 ? { headers: { connection: "close" } } : {}),
|
|
143
|
+
status,
|
|
144
|
+
}));
|
|
98
145
|
}
|
|
99
146
|
});
|
|
100
147
|
await new Promise((resolve, reject) => {
|
|
@@ -112,7 +159,7 @@ export async function startWebhookServer(params) {
|
|
|
112
159
|
async close() {
|
|
113
160
|
await closeServer(server);
|
|
114
161
|
},
|
|
115
|
-
endpointUrl: `http://${params.host}:${address.port}${params.path}`,
|
|
162
|
+
endpointUrl: `http://${formatUrlHost(params.host)}:${address.port}${params.path}`,
|
|
116
163
|
};
|
|
117
164
|
}
|
|
118
165
|
//# sourceMappingURL=webhook-server.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook-server.js","sourceRoot":"","sources":["../../../src/providers/webhook-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA0D,MAAM,WAAW,CAAC;AAOjG,MAAM,sBAAsB,GAAG,IAAI,GAAG,IAAI,CAAC;AAE3C,MAAM,wBAAyB,SAAQ,KAAK;CAAG;AAE/C,KAAK,UAAU,eAAe,CAAC,OAAwB,EAAE,YAAoB;IAC3E,OAAO,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnD,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC3B,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnE,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC;YAC3B,IAAI,SAAS,GAAG,YAAY,EAAE,CAAC;gBAC7B,OAAO,GAAG,IAAI,CAAC;gBACf,OAAO,CAAC,MAAM,EAAE,CAAC;gBACjB,MAAM,CAAC,IAAI,wBAAwB,EAAE,CAAC,CAAC;gBACvC,OAAO;YACT,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE;YACvB,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO;YACT,CAAC;YACD,OAAO,GAAG,IAAI,CAAC;YACf,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC9B,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO;YACT,CAAC;YACD,OAAO,GAAG,IAAI,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,OAAwB,EAAE,YAAoB;IAC1E,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,WAAW,CAAC;IACjD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,GAAG,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC;IAC1D,MAAM,IAAI,GACR,OAAO,CAAC,MAAM,KAAK,KAAK,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM;QACnD,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,MAAM,eAAe,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAEnD,MAAM,IAAI,GAAgB;QACxB,OAAO,EAAE,OAAO,CAAC,OAAiC;KACnD,CAAC;IACF,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAC/B,CAAC;IACD,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,QAAyC,EACzC,aAAuB;IAEvB,QAAQ,CAAC,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC;IAE3C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;QAClD,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;QACxB,QAAQ,CAAC,GAAG,EAAE,CAAC;QACf,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,aAAa,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5D,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACrB,CAAC;AAED,SAAS,WAAW,CAAC,MAAc;IACjC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACrB,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,CAAC,KAAK,CAAC,CAAC;gBACd,OAAO;YACT,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAOxC;IACC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACpD,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,sBAAsB,CAAC;IACnE,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;QACtD,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,MAAM,cAAc,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YACjE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;YACpD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,QAAQ,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC;gBAClE,MAAM,kBAAkB,CAAC,QAAQ,EAAE,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;gBAC/E,OAAO;YACT,CAAC;YAED,MAAM,kBAAkB,CAAC,QAAQ,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;QACxE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,MAAM,MAAM,GAAG,KAAK,YAAY,wBAAwB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;YACrE,MAAM,kBAAkB,CACtB,QAAQ,EACR,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,CAC9E,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;YAC3C,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC5B,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;IACjC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO;QACL,KAAK,CAAC,KAAK;YACT,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QACD,WAAW,EAAE,UAAU,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE;KACnE,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"webhook-server.js","sourceRoot":"","sources":["../../../src/providers/webhook-server.ts"],"names":[],"mappings":"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","sourcesContent":["import { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\";\n\nexport type StartedWebhookServer = {\n close(): Promise<void>;\n endpointUrl: string;\n};\n\nconst DEFAULT_MAX_BODY_BYTES = 1024 * 1024;\nconst DEFAULT_BODY_TIMEOUT_MS = 5_000;\n\nclass RequestBodyTooLargeError extends Error {}\nclass RequestBodyTimeoutError extends Error {}\n\nasync function readRequestBody(\n request: IncomingMessage,\n maxBodyBytes: number,\n bodyTimeoutMs: number,\n): Promise<Buffer> {\n return await new Promise<Buffer>((resolve, reject) => {\n const chunks: Buffer[] = [];\n let bodyBytes = 0;\n let settled = false;\n\n const cleanup = (preserveErrorListener = false) => {\n clearTimeout(timeout);\n request.off(\"data\", onData);\n request.off(\"end\", onEnd);\n if (!preserveErrorListener) {\n request.off(\"error\", onError);\n }\n request.off(\"aborted\", onAborted);\n };\n const fail = (error: unknown) => {\n if (settled) {\n return;\n }\n settled = true;\n cleanup(true);\n reject(error);\n };\n const onData = (chunk: Buffer | string) => {\n if (settled) {\n return;\n }\n\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n bodyBytes += buffer.length;\n if (bodyBytes > maxBodyBytes) {\n request.resume();\n fail(new RequestBodyTooLargeError());\n return;\n }\n chunks.push(buffer);\n };\n const onEnd = () => {\n if (settled) {\n return;\n }\n settled = true;\n cleanup();\n resolve(Buffer.concat(chunks));\n };\n const onError = (error: Error) => fail(error);\n const onAborted = () => fail(new Error(\"request body aborted\"));\n const timeout = setTimeout(() => {\n request.resume();\n fail(new RequestBodyTimeoutError());\n }, bodyTimeoutMs);\n\n request.on(\"data\", onData);\n request.once(\"end\", onEnd);\n request.once(\"error\", onError);\n request.once(\"aborted\", onAborted);\n });\n}\n\nasync function toFetchRequest(\n request: IncomingMessage,\n url: URL,\n maxBodyBytes: number,\n bodyTimeoutMs: number,\n): Promise<Request> {\n const body =\n request.method === \"GET\" || request.method === \"HEAD\"\n ? undefined\n : await readRequestBody(request, maxBodyBytes, bodyTimeoutMs);\n\n const init: RequestInit = {\n headers: request.headers as Record<string, string>,\n };\n if (request.method) {\n init.method = request.method;\n }\n if (body) {\n init.body = body;\n init.duplex = \"half\";\n }\n\n return new Request(url, init);\n}\n\nasync function writeFetchResponse(\n response: ServerResponse<IncomingMessage>,\n fetchResponse: Response,\n): Promise<void> {\n response.statusCode = fetchResponse.status;\n\n for (const [name, value] of fetchResponse.headers) {\n response.setHeader(name, value);\n }\n\n if (!fetchResponse.body) {\n response.end();\n return;\n }\n\n const body = Buffer.from(await fetchResponse.arrayBuffer());\n response.end(body);\n}\n\nfunction closeServer(server: Server): Promise<void> {\n return new Promise((resolve, reject) => {\n server.close((error) => {\n if (error) {\n reject(error);\n return;\n }\n resolve();\n });\n server.closeAllConnections();\n });\n}\n\nfunction formatUrlHost(host: string): string {\n return host.includes(\":\") && !host.startsWith(\"[\") ? `[${host}]` : host;\n}\n\nexport async function startWebhookServer(params: {\n handle(request: Request): Promise<Response>;\n bodyTimeoutMs?: number | undefined;\n host: string;\n maxBodyBytes?: number;\n methods?: readonly string[] | undefined;\n onError?: ((error: unknown) => void) | undefined;\n path: string;\n port: number;\n}): Promise<StartedWebhookServer> {\n const methods = new Set(params.methods ?? [\"POST\"]);\n const maxBodyBytes = params.maxBodyBytes ?? DEFAULT_MAX_BODY_BYTES;\n const bodyTimeoutMs = params.bodyTimeoutMs ?? DEFAULT_BODY_TIMEOUT_MS;\n const server = createServer(async (request, response) => {\n try {\n const method = request.method ?? \"GET\";\n const host = request.headers.host ?? \"127.0.0.1\";\n const url = new URL(request.url ?? \"/\", `http://${host}`);\n if (!methods.has(method) || url.pathname !== params.path) {\n request.resume();\n await writeFetchResponse(response, new Response(\"not found\", { status: 404 }));\n return;\n }\n\n const fetchRequest = await toFetchRequest(request, url, maxBodyBytes, bodyTimeoutMs);\n await writeFetchResponse(response, await params.handle(fetchRequest));\n } catch (error) {\n const status =\n error instanceof RequestBodyTooLargeError\n ? 413\n : error instanceof RequestBodyTimeoutError\n ? 408\n : 500;\n if (status === 500) {\n try {\n params.onError?.(error);\n } catch {\n // Error reporting must not change the public response.\n }\n }\n await writeFetchResponse(\n response,\n new Response(\n status === 413\n ? \"request body too large\"\n : status === 408\n ? \"request body timeout\"\n : \"internal server error\",\n {\n ...(status === 408 ? { headers: { connection: \"close\" } } : {}),\n status,\n },\n ),\n );\n }\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(params.port, params.host, () => {\n server.off(\"error\", reject);\n resolve();\n });\n });\n\n const address = server.address();\n if (!address || typeof address === \"string\") {\n throw new Error(\"Unable to resolve webhook server address.\");\n }\n\n return {\n async close() {\n await closeServer(server);\n },\n endpointUrl: `http://${formatUrlHost(params.host)}:${address.port}${params.path}`,\n };\n}\n"]}
|
|
@@ -7,15 +7,35 @@ export type ServerRequestEvent = {
|
|
|
7
7
|
query: Record<string, string>;
|
|
8
8
|
type: "admin" | "api";
|
|
9
9
|
};
|
|
10
|
+
export type HttpJsonHandlerResult = Response | {
|
|
11
|
+
onWriteFailure?(): Promise<void> | void;
|
|
12
|
+
onWriteSuccess?(): Promise<void> | void;
|
|
13
|
+
response: Response;
|
|
14
|
+
};
|
|
10
15
|
export declare const ADMIN_TOKEN_HEADER = "x-crabline-admin-token";
|
|
16
|
+
export declare const DEFAULT_MAX_REQUEST_BODY_BYTES: number;
|
|
17
|
+
export declare const DEFAULT_SERVER_SHUTDOWN_GRACE_MS = 250;
|
|
18
|
+
export declare class InvalidJsonBodyError extends Error {
|
|
19
|
+
constructor(cause: unknown);
|
|
20
|
+
}
|
|
21
|
+
export declare class RequestBodyTooLargeError extends Error {
|
|
22
|
+
readonly maxBytes: number;
|
|
23
|
+
constructor(maxBytes: number);
|
|
24
|
+
}
|
|
11
25
|
export declare function jsonResponse(value: unknown, status?: number): Response;
|
|
12
|
-
export declare function
|
|
26
|
+
export declare function drainRequestBody(request: IncomingMessage): void;
|
|
27
|
+
export declare function readBody(request: IncomingMessage, maxBytes?: number): Promise<Buffer>;
|
|
28
|
+
export declare function parseUnknownRequestBody(request: IncomingMessage, maxBytes?: number): Promise<unknown>;
|
|
13
29
|
export declare function parseRequestBody(request: IncomingMessage): Promise<Record<string, unknown>>;
|
|
30
|
+
export declare function isJsonObject(value: unknown): value is Record<string, unknown>;
|
|
14
31
|
export declare function queryRecord(url: URL): Record<string, string>;
|
|
32
|
+
export declare function formatUrlHost(host: string): string;
|
|
33
|
+
export declare function isLoopbackHost(host: string): boolean;
|
|
15
34
|
export declare function writeResponse(response: ServerResponse, fetchResponse: Response): Promise<void>;
|
|
16
|
-
export declare function closeServer(server: Server): Promise<void>;
|
|
35
|
+
export declare function closeServer(server: Server, graceMs?: number): Promise<void>;
|
|
17
36
|
export declare function startHttpJsonServer(params: {
|
|
18
|
-
handle: (request: IncomingMessage) => Promise<
|
|
37
|
+
handle: (request: IncomingMessage, response: ServerResponse) => Promise<HttpJsonHandlerResult>;
|
|
38
|
+
handleError?: (error: unknown, request: IncomingMessage) => Response | undefined;
|
|
19
39
|
host: string;
|
|
20
40
|
port: number;
|
|
21
41
|
serverName: string;
|
package/dist/src/servers/http.js
CHANGED
|
@@ -2,63 +2,255 @@ import { createServer } from "node:http";
|
|
|
2
2
|
import { timingSafeEqual } from "node:crypto";
|
|
3
3
|
import { CrablineError } from "../core/errors.js";
|
|
4
4
|
export const ADMIN_TOKEN_HEADER = "x-crabline-admin-token";
|
|
5
|
+
export const DEFAULT_MAX_REQUEST_BODY_BYTES = 1024 * 1024;
|
|
6
|
+
export const DEFAULT_SERVER_SHUTDOWN_GRACE_MS = 250;
|
|
7
|
+
export class InvalidJsonBodyError extends Error {
|
|
8
|
+
constructor(cause) {
|
|
9
|
+
super("Request body is not valid JSON.", { cause });
|
|
10
|
+
this.name = "InvalidJsonBodyError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class RequestBodyTooLargeError extends Error {
|
|
14
|
+
maxBytes;
|
|
15
|
+
constructor(maxBytes) {
|
|
16
|
+
super(`Request body exceeds the ${maxBytes} byte limit.`);
|
|
17
|
+
this.maxBytes = maxBytes;
|
|
18
|
+
this.name = "RequestBodyTooLargeError";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
5
21
|
export function jsonResponse(value, status = 200) {
|
|
6
22
|
return Response.json(value, { status });
|
|
7
23
|
}
|
|
8
|
-
export
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
24
|
+
export function drainRequestBody(request) {
|
|
25
|
+
const ignoreError = () => { };
|
|
26
|
+
request.on("error", ignoreError);
|
|
27
|
+
if (request.destroyed || request.readableEnded) {
|
|
28
|
+
return;
|
|
12
29
|
}
|
|
13
|
-
|
|
30
|
+
const cleanup = () => {
|
|
31
|
+
request.off("close", cleanup);
|
|
32
|
+
request.off("end", cleanup);
|
|
33
|
+
request.off("error", ignoreError);
|
|
34
|
+
};
|
|
35
|
+
request.once("close", cleanup);
|
|
36
|
+
request.once("end", cleanup);
|
|
37
|
+
request.resume();
|
|
14
38
|
}
|
|
15
|
-
export async function
|
|
16
|
-
const
|
|
39
|
+
export async function readBody(request, maxBytes = DEFAULT_MAX_REQUEST_BODY_BYTES) {
|
|
40
|
+
const contentLengthHeader = request.headers["content-length"];
|
|
41
|
+
const contentLengthValue = Array.isArray(contentLengthHeader)
|
|
42
|
+
? contentLengthHeader[0]
|
|
43
|
+
: contentLengthHeader;
|
|
44
|
+
if (contentLengthValue && /^\d+$/u.test(contentLengthValue)) {
|
|
45
|
+
const contentLength = Number(contentLengthValue);
|
|
46
|
+
if (!Number.isSafeInteger(contentLength) || contentLength > maxBytes) {
|
|
47
|
+
drainRequestBody(request);
|
|
48
|
+
throw new RequestBodyTooLargeError(maxBytes);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return await new Promise((resolve, reject) => {
|
|
52
|
+
const chunks = [];
|
|
53
|
+
let length = 0;
|
|
54
|
+
let settled = false;
|
|
55
|
+
const cleanup = () => {
|
|
56
|
+
request.off("aborted", onAborted);
|
|
57
|
+
request.off("data", onData);
|
|
58
|
+
request.off("end", onEnd);
|
|
59
|
+
request.off("error", onError);
|
|
60
|
+
};
|
|
61
|
+
const fail = (error) => {
|
|
62
|
+
if (settled) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
settled = true;
|
|
66
|
+
drainRequestBody(request);
|
|
67
|
+
cleanup();
|
|
68
|
+
reject(error);
|
|
69
|
+
};
|
|
70
|
+
const onAborted = () => fail(new Error("Request body stream was aborted."));
|
|
71
|
+
const onData = (chunk) => {
|
|
72
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
73
|
+
length += buffer.length;
|
|
74
|
+
if (length > maxBytes) {
|
|
75
|
+
fail(new RequestBodyTooLargeError(maxBytes));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
chunks.push(buffer);
|
|
79
|
+
};
|
|
80
|
+
const onEnd = () => {
|
|
81
|
+
if (settled) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
settled = true;
|
|
85
|
+
cleanup();
|
|
86
|
+
resolve(Buffer.concat(chunks, length));
|
|
87
|
+
};
|
|
88
|
+
const onError = (error) => fail(error);
|
|
89
|
+
request.on("aborted", onAborted);
|
|
90
|
+
request.on("data", onData);
|
|
91
|
+
request.on("end", onEnd);
|
|
92
|
+
request.on("error", onError);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
export async function parseUnknownRequestBody(request, maxBytes = DEFAULT_MAX_REQUEST_BODY_BYTES) {
|
|
96
|
+
const body = await readBody(request, maxBytes);
|
|
17
97
|
if (body.length === 0) {
|
|
18
98
|
return {};
|
|
19
99
|
}
|
|
20
100
|
const contentType = request.headers["content-type"] ?? "";
|
|
21
101
|
const includesJson = Array.isArray(contentType)
|
|
22
|
-
? contentType.some((entry) => entry.includes("json"))
|
|
23
|
-
: contentType.includes("json");
|
|
102
|
+
? contentType.some((entry) => entry.toLowerCase().includes("json"))
|
|
103
|
+
: contentType.toLowerCase().includes("json");
|
|
24
104
|
if (includesJson) {
|
|
25
|
-
|
|
105
|
+
try {
|
|
106
|
+
return JSON.parse(body.toString("utf8"));
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
throw new InvalidJsonBodyError(error);
|
|
110
|
+
}
|
|
26
111
|
}
|
|
27
112
|
const params = new URLSearchParams(body.toString("utf8"));
|
|
28
113
|
return Object.fromEntries(params.entries());
|
|
29
114
|
}
|
|
115
|
+
export async function parseRequestBody(request) {
|
|
116
|
+
return (await parseUnknownRequestBody(request, Number.MAX_SAFE_INTEGER));
|
|
117
|
+
}
|
|
118
|
+
export function isJsonObject(value) {
|
|
119
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
120
|
+
}
|
|
30
121
|
export function queryRecord(url) {
|
|
31
122
|
return Object.fromEntries(url.searchParams.entries());
|
|
32
123
|
}
|
|
124
|
+
export function formatUrlHost(host) {
|
|
125
|
+
return host.includes(":") ? `[${host}]` : host;
|
|
126
|
+
}
|
|
127
|
+
export function isLoopbackHost(host) {
|
|
128
|
+
const normalized = host
|
|
129
|
+
.trim()
|
|
130
|
+
.replace(/^\[(.*)\]$/u, "$1")
|
|
131
|
+
.toLowerCase();
|
|
132
|
+
return (normalized === "localhost" ||
|
|
133
|
+
normalized.endsWith(".localhost") ||
|
|
134
|
+
normalized === "::1" ||
|
|
135
|
+
normalized.startsWith("::ffff:127.") ||
|
|
136
|
+
/^127(?:\.\d{1,3}){3}$/u.test(normalized));
|
|
137
|
+
}
|
|
33
138
|
export async function writeResponse(response, fetchResponse) {
|
|
34
139
|
response.statusCode = fetchResponse.status;
|
|
35
140
|
for (const [name, value] of fetchResponse.headers) {
|
|
141
|
+
if (name.toLowerCase() === "set-cookie") {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
36
144
|
response.setHeader(name, value);
|
|
37
145
|
}
|
|
38
|
-
|
|
146
|
+
const setCookies = fetchResponse.headers.getSetCookie();
|
|
147
|
+
if (setCookies.length > 0) {
|
|
148
|
+
response.setHeader("set-cookie", setCookies);
|
|
149
|
+
}
|
|
150
|
+
const body = Buffer.from(await fetchResponse.arrayBuffer());
|
|
151
|
+
await new Promise((resolve, reject) => {
|
|
152
|
+
if (response.destroyed ||
|
|
153
|
+
response.req?.aborted ||
|
|
154
|
+
response.req?.socket.destroyed ||
|
|
155
|
+
response.socket?.destroyed) {
|
|
156
|
+
reject(new Error("HTTP response closed before delivery completed."));
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const cleanup = () => {
|
|
160
|
+
response.off("close", onClose);
|
|
161
|
+
response.off("error", onError);
|
|
162
|
+
response.off("finish", onFinish);
|
|
163
|
+
};
|
|
164
|
+
const onClose = () => {
|
|
165
|
+
if (response.writableFinished) {
|
|
166
|
+
cleanup();
|
|
167
|
+
resolve();
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
cleanup();
|
|
171
|
+
reject(new Error("HTTP response closed before delivery completed."));
|
|
172
|
+
};
|
|
173
|
+
const onError = (error) => {
|
|
174
|
+
cleanup();
|
|
175
|
+
reject(error);
|
|
176
|
+
};
|
|
177
|
+
const onFinish = () => {
|
|
178
|
+
cleanup();
|
|
179
|
+
resolve();
|
|
180
|
+
};
|
|
181
|
+
response.once("close", onClose);
|
|
182
|
+
response.once("error", onError);
|
|
183
|
+
response.once("finish", onFinish);
|
|
184
|
+
try {
|
|
185
|
+
response.end(body);
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
cleanup();
|
|
189
|
+
reject(error);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
39
192
|
}
|
|
40
|
-
export function closeServer(server) {
|
|
193
|
+
export function closeServer(server, graceMs = DEFAULT_SERVER_SHUTDOWN_GRACE_MS) {
|
|
41
194
|
return new Promise((resolve, reject) => {
|
|
195
|
+
const closeIdleInterval = setInterval(() => server.closeIdleConnections(), 25);
|
|
196
|
+
closeIdleInterval.unref();
|
|
197
|
+
const forceCloseTimer = setTimeout(() => {
|
|
198
|
+
server.closeAllConnections();
|
|
199
|
+
}, graceMs);
|
|
200
|
+
forceCloseTimer.unref();
|
|
42
201
|
server.close((error) => {
|
|
202
|
+
clearInterval(closeIdleInterval);
|
|
203
|
+
clearTimeout(forceCloseTimer);
|
|
43
204
|
if (error) {
|
|
44
205
|
reject(error);
|
|
45
206
|
return;
|
|
46
207
|
}
|
|
47
208
|
resolve();
|
|
48
209
|
});
|
|
210
|
+
server.closeIdleConnections();
|
|
49
211
|
});
|
|
50
212
|
}
|
|
51
213
|
export async function startHttpJsonServer(params) {
|
|
52
|
-
const
|
|
214
|
+
const handleRequest = async (request, response) => {
|
|
53
215
|
try {
|
|
54
|
-
|
|
216
|
+
const result = await params.handle(request, response);
|
|
217
|
+
const handled = result instanceof Response ? { response: result } : result;
|
|
218
|
+
try {
|
|
219
|
+
await writeResponse(response, handled.response);
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
await handled.onWriteFailure?.();
|
|
223
|
+
throw error;
|
|
224
|
+
}
|
|
225
|
+
try {
|
|
226
|
+
await handled.onWriteSuccess?.();
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
// Delivery is already committed; lifecycle failures must not trigger another response.
|
|
230
|
+
}
|
|
55
231
|
}
|
|
56
232
|
catch (error) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
233
|
+
let handled;
|
|
234
|
+
try {
|
|
235
|
+
handled = params.handleError?.(error, request);
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
handled = undefined;
|
|
239
|
+
}
|
|
240
|
+
try {
|
|
241
|
+
await writeResponse(response, handled ??
|
|
242
|
+
jsonResponse({
|
|
243
|
+
error: "internal server error",
|
|
244
|
+
ok: false,
|
|
245
|
+
}, 500));
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
response.destroy();
|
|
249
|
+
}
|
|
61
250
|
}
|
|
251
|
+
};
|
|
252
|
+
const server = createServer((request, response) => {
|
|
253
|
+
void handleRequest(request, response);
|
|
62
254
|
});
|
|
63
255
|
await new Promise((resolve, reject) => {
|
|
64
256
|
server.once("error", reject);
|
|
@@ -74,7 +266,7 @@ export async function startHttpJsonServer(params) {
|
|
|
74
266
|
});
|
|
75
267
|
}
|
|
76
268
|
return {
|
|
77
|
-
baseUrl: `http://${params.host
|
|
269
|
+
baseUrl: `http://${formatUrlHost(params.host)}:${address.port}`,
|
|
78
270
|
async close() {
|
|
79
271
|
await closeServer(server);
|
|
80
272
|
},
|
|
@@ -99,7 +291,8 @@ export function readInteger(value) {
|
|
|
99
291
|
if (!stringValue || !/^-?\d+$/u.test(stringValue)) {
|
|
100
292
|
return undefined;
|
|
101
293
|
}
|
|
102
|
-
|
|
294
|
+
const parsed = Number(stringValue);
|
|
295
|
+
return Number.isSafeInteger(parsed) ? parsed : undefined;
|
|
103
296
|
}
|
|
104
297
|
function readBearerToken(authorization) {
|
|
105
298
|
if (!authorization) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/servers/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA0D,MAAM,WAAW,CAAC;AACjG,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAWlD,MAAM,CAAC,MAAM,kBAAkB,GAAG,wBAAwB,CAAC;AAE3D,MAAM,UAAU,YAAY,CAAC,KAAc,EAAE,MAAM,GAAG,GAAG;IACvD,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAAwB;IACrD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAwB;IAC7D,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IAC1D,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;QAC7C,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACrD,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAA4B,CAAC;IACtE,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1D,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,GAAQ;IAClC,OAAO,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAwB,EACxB,aAAuB;IAEvB,QAAQ,CAAC,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC;IAC3C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;QAClD,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IACD,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,aAAa,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACrB,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,CAAC,KAAK,CAAC,CAAC;gBACd,OAAO;YACT,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAKzC;IACC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;QACtD,IAAI,CAAC;YACH,MAAM,aAAa,CAAC,QAAQ,EAAE,MAAM,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,aAAa,CACjB,QAAQ,EACR,YAAY,CACV;gBACE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;gBAC7D,EAAE,EAAE,KAAK;aACV,EACD,GAAG,CACJ,CACF,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IACH,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC7B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;YAC3C,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC5B,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;IACjC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC5C,MAAM,IAAI,aAAa,CAAC,qBAAqB,MAAM,CAAC,UAAU,wBAAwB,EAAE;YACtF,IAAI,EAAE,cAAc;SACrB,CAAC,CAAC;IACL,CAAC;IACD,OAAO;QACL,OAAO,EAAE,UAAU,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,EAAE;QACjG,KAAK,CAAC,KAAK;YACT,MAAM,WAAW,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;QACD,MAAM;KACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC3D,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAc;IAC9C,MAAM,WAAW,GAAG,UAAU,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IAC9C,OAAO,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,MAAM,WAAW,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;IAC7C,IAAI,CAAC,WAAW,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAClD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,eAAe,CAAC,aAAiC;IACxD,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,OAAO,GAAG,aAAa,CAAC,SAAS,EAAE,CAAC;IAC1C,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,SAAS,EAAE,CAAC;QACpD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAwB,EAAE,aAAqB;IAC3E,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACnD,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC/D,MAAM,aAAa,GAAG,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACpF,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAC5C,OAAO,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,IAAI,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,IAAI,QAAQ,CAAC,cAAc,EAAE;QAClC,OAAO,EAAE,EAAE,kBAAkB,EAAE,QAAQ,EAAE;QACzC,MAAM,EAAE,GAAG;KACZ,CAAC,CAAC;AACL,CAAC"}
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/servers/http.ts"],"names":[],"mappings":"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","sourcesContent":["import { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\";\nimport { timingSafeEqual } from \"node:crypto\";\nimport { CrablineError } from \"../core/errors.js\";\n\nexport type ServerRequestEvent = {\n at: string;\n body?: unknown;\n method: string;\n path: string;\n query: Record<string, string>;\n type: \"admin\" | \"api\";\n};\n\nexport type HttpJsonHandlerResult =\n | Response\n | {\n onWriteFailure?(): Promise<void> | void;\n onWriteSuccess?(): Promise<void> | void;\n response: Response;\n };\n\nexport const ADMIN_TOKEN_HEADER = \"x-crabline-admin-token\";\nexport const DEFAULT_MAX_REQUEST_BODY_BYTES = 1024 * 1024;\nexport const DEFAULT_SERVER_SHUTDOWN_GRACE_MS = 250;\n\nexport class InvalidJsonBodyError extends Error {\n constructor(cause: unknown) {\n super(\"Request body is not valid JSON.\", { cause });\n this.name = \"InvalidJsonBodyError\";\n }\n}\n\nexport class RequestBodyTooLargeError extends Error {\n constructor(readonly maxBytes: number) {\n super(`Request body exceeds the ${maxBytes} byte limit.`);\n this.name = \"RequestBodyTooLargeError\";\n }\n}\n\nexport function jsonResponse(value: unknown, status = 200): Response {\n return Response.json(value, { status });\n}\n\nexport function drainRequestBody(request: IncomingMessage): void {\n const ignoreError = () => {};\n request.on(\"error\", ignoreError);\n if (request.destroyed || request.readableEnded) {\n return;\n }\n const cleanup = () => {\n request.off(\"close\", cleanup);\n request.off(\"end\", cleanup);\n request.off(\"error\", ignoreError);\n };\n\n request.once(\"close\", cleanup);\n request.once(\"end\", cleanup);\n request.resume();\n}\n\nexport async function readBody(\n request: IncomingMessage,\n maxBytes = DEFAULT_MAX_REQUEST_BODY_BYTES,\n): Promise<Buffer> {\n const contentLengthHeader = request.headers[\"content-length\"];\n const contentLengthValue = Array.isArray(contentLengthHeader)\n ? contentLengthHeader[0]\n : contentLengthHeader;\n if (contentLengthValue && /^\\d+$/u.test(contentLengthValue)) {\n const contentLength = Number(contentLengthValue);\n if (!Number.isSafeInteger(contentLength) || contentLength > maxBytes) {\n drainRequestBody(request);\n throw new RequestBodyTooLargeError(maxBytes);\n }\n }\n\n return await new Promise<Buffer>((resolve, reject) => {\n const chunks: Buffer[] = [];\n let length = 0;\n let settled = false;\n\n const cleanup = () => {\n request.off(\"aborted\", onAborted);\n request.off(\"data\", onData);\n request.off(\"end\", onEnd);\n request.off(\"error\", onError);\n };\n const fail = (error: Error) => {\n if (settled) {\n return;\n }\n settled = true;\n drainRequestBody(request);\n cleanup();\n reject(error);\n };\n const onAborted = () => fail(new Error(\"Request body stream was aborted.\"));\n const onData = (chunk: Buffer | string) => {\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n length += buffer.length;\n if (length > maxBytes) {\n fail(new RequestBodyTooLargeError(maxBytes));\n return;\n }\n chunks.push(buffer);\n };\n const onEnd = () => {\n if (settled) {\n return;\n }\n settled = true;\n cleanup();\n resolve(Buffer.concat(chunks, length));\n };\n const onError = (error: Error) => fail(error);\n\n request.on(\"aborted\", onAborted);\n request.on(\"data\", onData);\n request.on(\"end\", onEnd);\n request.on(\"error\", onError);\n });\n}\n\nexport async function parseUnknownRequestBody(\n request: IncomingMessage,\n maxBytes = DEFAULT_MAX_REQUEST_BODY_BYTES,\n): Promise<unknown> {\n const body = await readBody(request, maxBytes);\n if (body.length === 0) {\n return {};\n }\n const contentType = request.headers[\"content-type\"] ?? \"\";\n const includesJson = Array.isArray(contentType)\n ? contentType.some((entry) => entry.toLowerCase().includes(\"json\"))\n : contentType.toLowerCase().includes(\"json\");\n if (includesJson) {\n try {\n return JSON.parse(body.toString(\"utf8\")) as unknown;\n } catch (error) {\n throw new InvalidJsonBodyError(error);\n }\n }\n const params = new URLSearchParams(body.toString(\"utf8\"));\n return Object.fromEntries(params.entries());\n}\n\nexport async function parseRequestBody(request: IncomingMessage): Promise<Record<string, unknown>> {\n return (await parseUnknownRequestBody(request, Number.MAX_SAFE_INTEGER)) as Record<\n string,\n unknown\n >;\n}\n\nexport function isJsonObject(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport function queryRecord(url: URL): Record<string, string> {\n return Object.fromEntries(url.searchParams.entries());\n}\n\nexport function formatUrlHost(host: string): string {\n return host.includes(\":\") ? `[${host}]` : host;\n}\n\nexport function isLoopbackHost(host: string): boolean {\n const normalized = host\n .trim()\n .replace(/^\\[(.*)\\]$/u, \"$1\")\n .toLowerCase();\n return (\n normalized === \"localhost\" ||\n normalized.endsWith(\".localhost\") ||\n normalized === \"::1\" ||\n normalized.startsWith(\"::ffff:127.\") ||\n /^127(?:\\.\\d{1,3}){3}$/u.test(normalized)\n );\n}\n\nexport async function writeResponse(\n response: ServerResponse,\n fetchResponse: Response,\n): Promise<void> {\n response.statusCode = fetchResponse.status;\n for (const [name, value] of fetchResponse.headers) {\n if (name.toLowerCase() === \"set-cookie\") {\n continue;\n }\n response.setHeader(name, value);\n }\n const setCookies = fetchResponse.headers.getSetCookie();\n if (setCookies.length > 0) {\n response.setHeader(\"set-cookie\", setCookies);\n }\n const body = Buffer.from(await fetchResponse.arrayBuffer());\n await new Promise<void>((resolve, reject) => {\n if (\n response.destroyed ||\n response.req?.aborted ||\n response.req?.socket.destroyed ||\n response.socket?.destroyed\n ) {\n reject(new Error(\"HTTP response closed before delivery completed.\"));\n return;\n }\n const cleanup = () => {\n response.off(\"close\", onClose);\n response.off(\"error\", onError);\n response.off(\"finish\", onFinish);\n };\n const onClose = () => {\n if (response.writableFinished) {\n cleanup();\n resolve();\n return;\n }\n cleanup();\n reject(new Error(\"HTTP response closed before delivery completed.\"));\n };\n const onError = (error: Error) => {\n cleanup();\n reject(error);\n };\n const onFinish = () => {\n cleanup();\n resolve();\n };\n response.once(\"close\", onClose);\n response.once(\"error\", onError);\n response.once(\"finish\", onFinish);\n try {\n response.end(body);\n } catch (error) {\n cleanup();\n reject(error);\n }\n });\n}\n\nexport function closeServer(\n server: Server,\n graceMs = DEFAULT_SERVER_SHUTDOWN_GRACE_MS,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const closeIdleInterval = setInterval(() => server.closeIdleConnections(), 25);\n closeIdleInterval.unref();\n const forceCloseTimer = setTimeout(() => {\n server.closeAllConnections();\n }, graceMs);\n forceCloseTimer.unref();\n server.close((error) => {\n clearInterval(closeIdleInterval);\n clearTimeout(forceCloseTimer);\n if (error) {\n reject(error);\n return;\n }\n resolve();\n });\n server.closeIdleConnections();\n });\n}\n\nexport async function startHttpJsonServer(params: {\n handle: (request: IncomingMessage, response: ServerResponse) => Promise<HttpJsonHandlerResult>;\n handleError?: (error: unknown, request: IncomingMessage) => Response | undefined;\n host: string;\n port: number;\n serverName: string;\n}): Promise<{ baseUrl: string; close(): Promise<void>; server: Server }> {\n const handleRequest = async (request: IncomingMessage, response: ServerResponse) => {\n try {\n const result = await params.handle(request, response);\n const handled = result instanceof Response ? { response: result } : result;\n try {\n await writeResponse(response, handled.response);\n } catch (error) {\n await handled.onWriteFailure?.();\n throw error;\n }\n try {\n await handled.onWriteSuccess?.();\n } catch {\n // Delivery is already committed; lifecycle failures must not trigger another response.\n }\n } catch (error) {\n let handled: Response | undefined;\n try {\n handled = params.handleError?.(error, request);\n } catch {\n handled = undefined;\n }\n try {\n await writeResponse(\n response,\n handled ??\n jsonResponse(\n {\n error: \"internal server error\",\n ok: false,\n },\n 500,\n ),\n );\n } catch {\n response.destroy();\n }\n }\n };\n const server = createServer((request, response) => {\n void handleRequest(request, response);\n });\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(params.port, params.host, () => {\n server.off(\"error\", reject);\n resolve();\n });\n });\n const address = server.address();\n if (!address || typeof address === \"string\") {\n throw new CrablineError(`Unable to resolve ${params.serverName} local server address.`, {\n kind: \"connectivity\",\n });\n }\n return {\n baseUrl: `http://${formatUrlHost(params.host)}:${address.port}`,\n async close() {\n await closeServer(server);\n },\n server,\n };\n}\n\nexport function readString(value: unknown): string | undefined {\n if (typeof value === \"string\" && value.length > 0) {\n return value;\n }\n if (typeof value === \"number\" || typeof value === \"bigint\") {\n return value.toString();\n }\n return undefined;\n}\n\nexport function readTrimmedString(value: unknown): string | undefined {\n const stringValue = readString(value)?.trim();\n return stringValue ? stringValue : undefined;\n}\n\nexport function readInteger(value: unknown): number | undefined {\n const stringValue = readTrimmedString(value);\n if (!stringValue || !/^-?\\d+$/u.test(stringValue)) {\n return undefined;\n }\n const parsed = Number(stringValue);\n return Number.isSafeInteger(parsed) ? parsed : undefined;\n}\n\nfunction readBearerToken(authorization: string | undefined): string | undefined {\n if (!authorization) {\n return undefined;\n }\n const trimmed = authorization.trimStart();\n if (trimmed.slice(0, 7).toLowerCase() !== \"bearer \") {\n return undefined;\n }\n return trimmed.slice(7);\n}\n\nexport function hasAdminToken(request: IncomingMessage, expectedToken: string): boolean {\n const header = request.headers[ADMIN_TOKEN_HEADER];\n const directToken = Array.isArray(header) ? header[0] : header;\n const providedToken = directToken ?? readBearerToken(request.headers.authorization);\n if (!providedToken) {\n return false;\n }\n\n const provided = Buffer.from(providedToken);\n const expected = Buffer.from(expectedToken);\n return provided.length === expected.length && timingSafeEqual(provided, expected);\n}\n\nexport function adminAuthError(): Response {\n return new Response(\"unauthorized\", {\n headers: { \"www-authenticate\": \"Bearer\" },\n status: 401,\n });\n}\n"]}
|