@nifrajs/core 5.5.0 → 5.6.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/CHANGELOG.md +159 -0
- package/dist/assurance.d.ts.map +1 -1
- package/dist/assurance.js.map +1 -1
- package/dist/evidence.d.ts +2 -0
- package/dist/evidence.d.ts.map +1 -1
- package/dist/evidence.js +2 -0
- package/dist/evidence.js.map +1 -1
- package/dist/file-type.d.ts +30 -0
- package/dist/file-type.d.ts.map +1 -0
- package/dist/file-type.js +118 -0
- package/dist/file-type.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/route-program.d.ts +11 -0
- package/dist/internal/route-program.d.ts.map +1 -1
- package/dist/internal/route-program.js +133 -85
- package/dist/internal/route-program.js.map +1 -1
- package/dist/reflection.d.ts +14 -1
- package/dist/reflection.d.ts.map +1 -1
- package/dist/reflection.js +34 -7
- package/dist/reflection.js.map +1 -1
- package/dist/response-observer.d.ts +1 -0
- package/dist/response-observer.d.ts.map +1 -1
- package/dist/response-observer.js +1 -0
- package/dist/response-observer.js.map +1 -1
- package/dist/server/bare-error-lane.d.ts +4 -1
- package/dist/server/bare-error-lane.d.ts.map +1 -1
- package/dist/server/bare-error-lane.js +9 -3
- package/dist/server/bare-error-lane.js.map +1 -1
- package/dist/server/before-handler.d.ts +10 -0
- package/dist/server/before-handler.d.ts.map +1 -0
- package/dist/server/before-handler.js +12 -0
- package/dist/server/before-handler.js.map +1 -0
- package/dist/server/body-lane.d.ts.map +1 -1
- package/dist/server/body-lane.js +8 -2
- package/dist/server/body-lane.js.map +1 -1
- package/dist/server/body-parser.d.ts.map +1 -1
- package/dist/server/body-parser.js +2 -5
- package/dist/server/body-parser.js.map +1 -1
- package/dist/server/body.d.ts +24 -8
- package/dist/server/body.d.ts.map +1 -1
- package/dist/server/body.js +86 -33
- package/dist/server/body.js.map +1 -1
- package/dist/server/core-copies.js +1 -1
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +6 -17
- package/dist/server/http.js.map +1 -1
- package/dist/server/multipart.d.ts +3 -0
- package/dist/server/multipart.d.ts.map +1 -1
- package/dist/server/multipart.js +226 -97
- package/dist/server/multipart.js.map +1 -1
- package/dist/server/proto-guard.d.ts.map +1 -1
- package/dist/server/proto-guard.js +39 -4
- package/dist/server/proto-guard.js.map +1 -1
- package/dist/server/query.d.ts.map +1 -1
- package/dist/server/query.js +8 -14
- package/dist/server/query.js.map +1 -1
- package/dist/server/repeated-prefix.d.ts +17 -0
- package/dist/server/repeated-prefix.d.ts.map +1 -0
- package/dist/server/repeated-prefix.js +17 -0
- package/dist/server/repeated-prefix.js.map +1 -0
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js +1 -3
- package/dist/server/request-context.js.map +1 -1
- package/dist/server/respond.d.ts +1 -3
- package/dist/server/respond.d.ts.map +1 -1
- package/dist/server/respond.js +21 -16
- package/dist/server/respond.js.map +1 -1
- package/dist/server/response-contract-lane.d.ts +12 -2
- package/dist/server/response-contract-lane.d.ts.map +1 -1
- package/dist/server/response-contract-lane.js +135 -8
- package/dist/server/response-contract-lane.js.map +1 -1
- package/dist/server/runtime-core.d.ts +7 -0
- package/dist/server/runtime-core.d.ts.map +1 -1
- package/dist/server/runtime-core.js +8 -1
- package/dist/server/runtime-core.js.map +1 -1
- package/dist/server/server-types.d.ts +6 -3
- package/dist/server/server-types.d.ts.map +1 -1
- package/dist/server/server.d.ts +6 -2
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +239 -78
- package/dist/server/server.js.map +1 -1
- package/dist/server/sse.d.ts +1 -1
- package/dist/server/sse.d.ts.map +1 -1
- package/dist/server/sse.js +5 -4
- package/dist/server/sse.js.map +1 -1
- package/dist/server/webhook.d.ts +1 -1
- package/dist/server/webhook.d.ts.map +1 -1
- package/dist/server/webhook.js +24 -19
- package/dist/server/webhook.js.map +1 -1
- package/dist/server/websocket.d.ts +18 -3
- package/dist/server/websocket.d.ts.map +1 -1
- package/dist/server/websocket.js +45 -5
- package/dist/server/websocket.js.map +1 -1
- package/dist/server/ws-bun.d.ts.map +1 -1
- package/dist/server/ws-bun.js +12 -3
- package/dist/server/ws-bun.js.map +1 -1
- package/dist/server.d.ts +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -0
- package/dist/server.js.map +1 -1
- package/dist/tool-cli.d.ts +64 -0
- package/dist/tool-cli.d.ts.map +1 -0
- package/dist/tool-cli.js +495 -0
- package/dist/tool-cli.js.map +1 -0
- package/package.json +11 -1
- package/src/assurance.ts +1 -0
- package/src/evidence.ts +4 -0
- package/src/file-type.ts +130 -0
- package/src/index.ts +2 -1
- package/src/internal/route-program.ts +261 -93
- package/src/reflection.ts +53 -7
- package/src/response-observer.ts +6 -0
- package/src/server/bare-error-lane.ts +9 -4
- package/src/server/before-handler.ts +14 -0
- package/src/server/body-lane.ts +19 -9
- package/src/server/body-parser.ts +1 -5
- package/src/server/body.ts +96 -36
- package/src/server/core-copies.ts +1 -1
- package/src/server/http.ts +6 -15
- package/src/server/multipart.ts +232 -100
- package/src/server/proto-guard.ts +39 -4
- package/src/server/query.ts +7 -13
- package/src/server/repeated-prefix.ts +25 -0
- package/src/server/request-context.ts +1 -3
- package/src/server/respond.ts +23 -15
- package/src/server/response-contract-lane.ts +130 -8
- package/src/server/runtime-core.ts +10 -1
- package/src/server/server-types.ts +6 -3
- package/src/server/server.ts +265 -76
- package/src/server/sse.ts +6 -5
- package/src/server/webhook.ts +29 -24
- package/src/server/websocket.ts +57 -8
- package/src/server/ws-bun.ts +17 -2
- package/src/server.ts +1 -0
- package/src/tool-cli.ts +584 -0
package/src/server/webhook.ts
CHANGED
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* this reads the body bounded (DoS guard, shared with `c.boundedBody`) and verifies before handing
|
|
5
5
|
* back the raw text for the handler to parse with its own schema.
|
|
6
6
|
*
|
|
7
|
-
* Verification is **constant-time**: the
|
|
8
|
-
* (WebCrypto)
|
|
9
|
-
* can't be discovered through timing
|
|
7
|
+
* Verification is **constant-time**: the expected HMAC is computed once per secret with
|
|
8
|
+
* `crypto.subtle.sign` (WebCrypto) and compared to each signature the header lists without an early
|
|
9
|
+
* exit - so a wrong signature can't be discovered through timing, and a header listing many
|
|
10
|
+
* signatures costs no extra HMAC over the body. WebCrypto-only, so it runs on Bun / Node / Deno / workerd.
|
|
10
11
|
*
|
|
11
12
|
* Presets cover Stripe (`t=…,v1=…` with a replay-window check) and GitHub (`sha256=…`); `generic`
|
|
12
13
|
* takes an explicit header + encoding for any other provider.
|
|
@@ -48,6 +49,7 @@ export type WebhookFailureReason =
|
|
|
48
49
|
| "malformed_signature"
|
|
49
50
|
| "payload_too_large"
|
|
50
51
|
| "invalid_content_length"
|
|
52
|
+
| "invalid_body"
|
|
51
53
|
|
|
52
54
|
/** Verified ⇒ the raw `payload` text (parse it with your schema). Rejected ⇒ a stable `reason`. */
|
|
53
55
|
export type WebhookResult =
|
|
@@ -74,7 +76,7 @@ const importHmacKey = (secret: string): Promise<CryptoKey> => {
|
|
|
74
76
|
TEXT.encode(secret),
|
|
75
77
|
{ name: "HMAC", hash: "SHA-256" },
|
|
76
78
|
false,
|
|
77
|
-
["
|
|
79
|
+
["sign"],
|
|
78
80
|
)
|
|
79
81
|
}
|
|
80
82
|
|
|
@@ -120,17 +122,26 @@ const decodeSignature = (
|
|
|
120
122
|
? fromBase64Url(value)
|
|
121
123
|
: fromBase64(value)
|
|
122
124
|
|
|
123
|
-
/**
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
125
|
+
/** The HMAC-SHA256 of `payload` under each of `keys`. */
|
|
126
|
+
const expectedMacs = (keys: readonly CryptoKey[], payload: Uint8Array): Promise<Uint8Array[]> =>
|
|
127
|
+
Promise.all(
|
|
128
|
+
keys.map(
|
|
129
|
+
async (key) =>
|
|
130
|
+
new Uint8Array(await crypto.subtle.sign("HMAC", key, payload as Uint8Array<ArrayBuffer>)),
|
|
131
|
+
),
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
/** True iff `sig` equals one of `macs`. Every byte of a same-length MAC is visited; a MAC's length is
|
|
135
|
+
* fixed (32 bytes), so a length mismatch reveals nothing. */
|
|
136
|
+
function matchesAny(macs: readonly Uint8Array[], sig: Uint8Array): boolean {
|
|
137
|
+
let matched = false
|
|
138
|
+
for (const mac of macs) {
|
|
139
|
+
if (mac.length !== sig.length) continue
|
|
140
|
+
let diff = 0
|
|
141
|
+
for (let i = 0; i < mac.length; i++) diff |= (mac[i] ?? 0) ^ (sig[i] ?? 0)
|
|
142
|
+
if (diff === 0) matched = true
|
|
132
143
|
}
|
|
133
|
-
return
|
|
144
|
+
return matched
|
|
134
145
|
}
|
|
135
146
|
|
|
136
147
|
// Parse a Stripe `Stripe-Signature` header: `t=<unix>,v1=<hex>[,v1=<hex>…]` (other schemes ignored).
|
|
@@ -193,10 +204,7 @@ export async function verifyWebhook(
|
|
|
193
204
|
|
|
194
205
|
const read = await readBoundedBytes(req, maxBytes)
|
|
195
206
|
if (!read.ok) {
|
|
196
|
-
return {
|
|
197
|
-
ok: false,
|
|
198
|
-
reason: read.status === 413 ? "payload_too_large" : "invalid_content_length",
|
|
199
|
-
}
|
|
207
|
+
return { ok: false, reason: read.error }
|
|
200
208
|
}
|
|
201
209
|
const payload = new TextDecoder().decode(read.bytes)
|
|
202
210
|
|
|
@@ -209,14 +217,11 @@ export async function verifyWebhook(
|
|
|
209
217
|
if (preset.timestamped) {
|
|
210
218
|
const parsed = parseStripeHeader(headerValue)
|
|
211
219
|
if (parsed === null) return { ok: false, reason: "malformed_signature" }
|
|
212
|
-
const
|
|
220
|
+
const macs = await expectedMacs(keys, TEXT.encode(`${parsed.t}.${payload}`))
|
|
213
221
|
let matched = false
|
|
214
222
|
for (const v1 of parsed.v1) {
|
|
215
223
|
const sig = decodeSignature(v1, encoding)
|
|
216
|
-
if (sig !== null && (
|
|
217
|
-
matched = true
|
|
218
|
-
break
|
|
219
|
-
}
|
|
224
|
+
if (sig !== null && matchesAny(macs, sig)) matched = true
|
|
220
225
|
}
|
|
221
226
|
if (!matched) return { ok: false, reason: "invalid_signature" }
|
|
222
227
|
// The signature covers `t`, so `t` is authentic once matched - now enforce the replay window.
|
|
@@ -232,6 +237,6 @@ export async function verifyWebhook(
|
|
|
232
237
|
prefix !== "" && headerValue.startsWith(prefix) ? headerValue.slice(prefix.length) : headerValue
|
|
233
238
|
const sig = decodeSignature(raw, encoding)
|
|
234
239
|
if (sig === null) return { ok: false, reason: "malformed_signature" }
|
|
235
|
-
if (await
|
|
240
|
+
if (matchesAny(await expectedMacs(keys, read.bytes), sig)) return { ok: true, payload }
|
|
236
241
|
return { ok: false, reason: "invalid_signature" }
|
|
237
242
|
}
|
package/src/server/websocket.ts
CHANGED
|
@@ -18,7 +18,7 @@ import type {
|
|
|
18
18
|
import { validateStandard } from "../schema/standard.ts"
|
|
19
19
|
import { decodeTransportFrame, type TransportCodecRegistry } from "../transport-codec.ts"
|
|
20
20
|
import { guardDecodedValue, type ProtoPoisoning, parseJsonGuarded } from "./proto-guard.ts"
|
|
21
|
-
import { isResponseResult } from "./runtime-core.ts"
|
|
21
|
+
import { isResponseResult, type StatusResponse } from "./runtime-core.ts"
|
|
22
22
|
|
|
23
23
|
type MaybePromise<T> = T | Promise<T>
|
|
24
24
|
|
|
@@ -35,7 +35,9 @@ type WsMessageInput<Schema extends StandardSchemaV1 | undefined> = Schema extend
|
|
|
35
35
|
export interface NifraWebSocket<Data = unknown> {
|
|
36
36
|
/** Send a text (`string`) or binary (`ArrayBuffer`/typed-array) frame. No-op once closed. */
|
|
37
37
|
send(data: string | ArrayBufferView | ArrayBuffer): void
|
|
38
|
-
/** Close the connection
|
|
38
|
+
/** Close the connection, with a code an endpoint may send (1000-1003, 1007-1014, 3000-4999;
|
|
39
|
+
* 1000 when none is given, on every runtime) and a reason of at most 123 UTF-8 bytes. Any other
|
|
40
|
+
* close throws a `RangeError`, and the socket stays open. */
|
|
39
41
|
close(code?: number, reason?: string): void
|
|
40
42
|
/** `WebSocket.readyState` (0 CONNECTING · 1 OPEN · 2 CLOSING · 3 CLOSED). */
|
|
41
43
|
readonly readyState: number
|
|
@@ -170,7 +172,7 @@ export interface WebSocketHandler<
|
|
|
170
172
|
* `data: undefined`. A thrown `Response` rejects with it; any other throw goes to the route's
|
|
171
173
|
* `onError` hooks, then a flat 500.
|
|
172
174
|
*/
|
|
173
|
-
upgrade?(c: WebSocketContext<Env> & Extra): MaybePromise<Data | Response>
|
|
175
|
+
upgrade?(c: WebSocketContext<Env> & Extra): MaybePromise<Data | Response | StatusResponse>
|
|
174
176
|
/**
|
|
175
177
|
* Contract-first messages: a Standard Schema (`t`, zod, valibot, …) validating each **inbound** frame.
|
|
176
178
|
* Text frames are parsed as JSON first. When set, `message` receives the validated, typed value; a
|
|
@@ -211,6 +213,9 @@ export interface WebSocketHandler<
|
|
|
211
213
|
issues: ReadonlyArray<StandardIssue>,
|
|
212
214
|
raw: WebSocketData,
|
|
213
215
|
): MaybePromise<void>
|
|
216
|
+
/** The connection closed. `code` and `reason` are the server's own close when it closed first
|
|
217
|
+
* (`ws.close()`, or 1009 for a message over the cap), the peer's when the peer did, and 1006 when
|
|
218
|
+
* the connection dropped without a close frame. */
|
|
214
219
|
close?(ws: NifraWebSocket<Data>, code: number, reason: string): MaybePromise<void>
|
|
215
220
|
error?(ws: NifraWebSocket<Data>, error: unknown): MaybePromise<void>
|
|
216
221
|
}
|
|
@@ -314,9 +319,20 @@ export function attachWebSocket<
|
|
|
314
319
|
handler.transport,
|
|
315
320
|
reportError,
|
|
316
321
|
)
|
|
322
|
+
// The runtime's close event carries the peer's echo, which may drop the reason; `close` is given
|
|
323
|
+
// the server's own close when the server closed first, as on Bun.
|
|
324
|
+
let sentClose: readonly [number, string] | undefined
|
|
325
|
+
// A close with no code is 1000 here as on Bun, whose close() cannot send one without a status.
|
|
326
|
+
const closeSocket = (code = 1000, reason?: string): void => {
|
|
327
|
+
if (sentClose === undefined && socket.readyState <= 1) sentClose = [code, reason ?? ""]
|
|
328
|
+
socket.close(code, reason)
|
|
329
|
+
}
|
|
317
330
|
ws = {
|
|
318
331
|
send,
|
|
319
|
-
close: (code, reason) =>
|
|
332
|
+
close: (code, reason) => {
|
|
333
|
+
assertCloseArgs(code, reason)
|
|
334
|
+
closeSocket(code, reason)
|
|
335
|
+
},
|
|
320
336
|
get readyState() {
|
|
321
337
|
return socket.readyState
|
|
322
338
|
},
|
|
@@ -342,7 +358,7 @@ export function attachWebSocket<
|
|
|
342
358
|
// The runtime hands over each message whole, so this bounds what reaches the handler, not what
|
|
343
359
|
// the runtime buffered to deliver it.
|
|
344
360
|
if (maxPayloadBytes !== undefined && exceedsPayloadCap(payload, maxPayloadBytes)) {
|
|
345
|
-
|
|
361
|
+
closeSocket(1009, "message too large")
|
|
346
362
|
return
|
|
347
363
|
}
|
|
348
364
|
safe(() =>
|
|
@@ -357,7 +373,8 @@ export function attachWebSocket<
|
|
|
357
373
|
"close",
|
|
358
374
|
(event: { readonly code?: number; readonly reason?: string }) => {
|
|
359
375
|
pubsub.unsubscribeAll(ws) // drop topic subscriptions so the registry never holds a dead socket
|
|
360
|
-
|
|
376
|
+
const [code, reason] = sentClose ?? [event.code ?? 1005, event.reason ?? ""]
|
|
377
|
+
safe(() => handler.close?.(ws, code, reason))
|
|
361
378
|
},
|
|
362
379
|
)
|
|
363
380
|
socket.addEventListener("error", (event: unknown) => reportError(event))
|
|
@@ -372,7 +389,8 @@ export function attachWebSocket<
|
|
|
372
389
|
const WS_MESSAGE_DECODER = new TextDecoder()
|
|
373
390
|
|
|
374
391
|
/** Whether a message is over `cap` UTF-8 bytes, without encoding a text one: each UTF-16 unit takes
|
|
375
|
-
* 1-3 bytes (a surrogate pair 4 for its 2
|
|
392
|
+
* 1-3 bytes (a surrogate pair 4 for its 2, a lone surrogate the 3 of U+FFFD), so only a length
|
|
393
|
+
* between those bounds is counted. */
|
|
376
394
|
export function exceedsPayloadCap(
|
|
377
395
|
message: string | ArrayBuffer | Uint8Array,
|
|
378
396
|
cap: number,
|
|
@@ -384,12 +402,43 @@ export function exceedsPayloadCap(
|
|
|
384
402
|
let bytes = 0
|
|
385
403
|
for (let i = 0; i < units; i++) {
|
|
386
404
|
const unit = message.charCodeAt(i)
|
|
387
|
-
|
|
405
|
+
if (unit >= 0xd800 && unit <= 0xdbff && (message.charCodeAt(i + 1) & 0xfc00) === 0xdc00) {
|
|
406
|
+
bytes += 4
|
|
407
|
+
i++
|
|
408
|
+
} else bytes += unit < 0x80 ? 1 : unit < 0x800 ? 2 : 3
|
|
388
409
|
if (bytes > cap) return true
|
|
389
410
|
}
|
|
390
411
|
return false
|
|
391
412
|
}
|
|
392
413
|
|
|
414
|
+
/**
|
|
415
|
+
* Refuse a close RFC 6455 forbids before the runtime sees it: a code outside 1000-1003, 1007-1014 and
|
|
416
|
+
* 3000-4999, a reason over 123 UTF-8 bytes, or a reason without a code. Runtimes disagreed on such a
|
|
417
|
+
* close - Bun and Deno sent it, Node's `ws` threw after marking the socket closing, which left it
|
|
418
|
+
* half-open, and workerd threw - so every adapter throws this `RangeError` first and the socket stays
|
|
419
|
+
* open.
|
|
420
|
+
*/
|
|
421
|
+
export function assertCloseArgs(code: number | undefined, reason: string | undefined): void {
|
|
422
|
+
if (code === undefined) {
|
|
423
|
+
if (reason !== undefined && reason !== "")
|
|
424
|
+
throw new RangeError("ws.close(): a reason needs a code")
|
|
425
|
+
return
|
|
426
|
+
}
|
|
427
|
+
if (
|
|
428
|
+
!Number.isInteger(code) ||
|
|
429
|
+
!(
|
|
430
|
+
(code >= 1000 && code <= 1003) ||
|
|
431
|
+
(code >= 1007 && code <= 1014) ||
|
|
432
|
+
(code >= 3000 && code <= 4999)
|
|
433
|
+
)
|
|
434
|
+
)
|
|
435
|
+
throw new RangeError(
|
|
436
|
+
`ws.close(): ${code} is not a code a server may send (1000-1003, 1007-1014, 3000-4999)`,
|
|
437
|
+
)
|
|
438
|
+
if (reason !== undefined && exceedsPayloadCap(reason, 123))
|
|
439
|
+
throw new RangeError("ws.close(): the reason is over 123 UTF-8 bytes")
|
|
440
|
+
}
|
|
441
|
+
|
|
393
442
|
type WebSocketSendPayload = string | ArrayBufferView | ArrayBuffer
|
|
394
443
|
|
|
395
444
|
const OUTBOUND_VALIDATION_ERROR = "outbound WebSocket frame failed sendSchema validation"
|
package/src/server/ws-bun.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
|
+
assertCloseArgs,
|
|
9
10
|
createWebSocketSender,
|
|
10
11
|
exceedsPayloadCap,
|
|
11
12
|
type NifraWebSocket,
|
|
@@ -103,7 +104,10 @@ function wrapBunSocket(
|
|
|
103
104
|
)
|
|
104
105
|
ws = {
|
|
105
106
|
send,
|
|
106
|
-
close: (code, reason) =>
|
|
107
|
+
close: (code, reason) => {
|
|
108
|
+
assertCloseArgs(code, reason)
|
|
109
|
+
raw.close(code, reason)
|
|
110
|
+
},
|
|
107
111
|
get readyState() {
|
|
108
112
|
return raw.readyState
|
|
109
113
|
},
|
|
@@ -149,6 +153,8 @@ function dispatchWsCallback(
|
|
|
149
153
|
}
|
|
150
154
|
}
|
|
151
155
|
|
|
156
|
+
const BUN_TOO_BIG_REASON = "Received too big message"
|
|
157
|
+
|
|
152
158
|
/**
|
|
153
159
|
* The shared Bun `websocket` dispatcher config for one app - each connection's `ws.data.handler` is
|
|
154
160
|
* the matched route's handler, set by `server.upgrade`.
|
|
@@ -204,7 +210,16 @@ export function createBunWsHandlers(
|
|
|
204
210
|
// Registry mode: drop topic subscriptions so it never holds a dead socket. Native mode: Bun
|
|
205
211
|
// unsubscribes the socket from every topic on close, so there is nothing to sweep here.
|
|
206
212
|
if (!nativePubsub) (ws.data.pubsub ?? topics).unsubscribeAll(nifra)
|
|
207
|
-
|
|
213
|
+
// Bun's own maxPayloadLength reports 1006 here, whether it dropped the connection (up to 1.4.3)
|
|
214
|
+
// or sent the peer a 1009 (from 1.4.4); the handler gets the 1009 every other payload cap reports.
|
|
215
|
+
const oversize = code === 1006 && reason === BUN_TOO_BIG_REASON
|
|
216
|
+
const closeCode = oversize ? 1009 : code
|
|
217
|
+
const closeReason = oversize ? "message too large" : reason
|
|
218
|
+
dispatchWsCallback(
|
|
219
|
+
() => ws.data.handler.close?.(nifra, closeCode, closeReason),
|
|
220
|
+
nifra,
|
|
221
|
+
ws.data.handler,
|
|
222
|
+
)
|
|
208
223
|
},
|
|
209
224
|
}
|
|
210
225
|
}
|