@nifrajs/core 5.12.0 → 5.13.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 +28 -0
- package/dist/edge-kit.d.ts +2 -1
- package/dist/edge-kit.d.ts.map +1 -1
- package/dist/edge-kit.js +2 -1
- package/dist/edge-kit.js.map +1 -1
- package/dist/idempotency.d.ts +12 -2
- package/dist/idempotency.d.ts.map +1 -1
- package/dist/idempotency.js +40 -22
- package/dist/idempotency.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/route-execution.d.ts +3 -0
- package/dist/internal/route-execution.d.ts.map +1 -1
- package/dist/server/body-lane.d.ts +12 -0
- package/dist/server/body-lane.d.ts.map +1 -1
- package/dist/server/body-lane.js +27 -0
- package/dist/server/body-lane.js.map +1 -1
- package/dist/server/core-copies.js +1 -1
- package/dist/server/request-context.d.ts.map +1 -1
- package/dist/server/request-context.js +8 -4
- package/dist/server/request-context.js.map +1 -1
- package/dist/server/respond.d.ts.map +1 -1
- package/dist/server/respond.js +10 -0
- package/dist/server/respond.js.map +1 -1
- package/dist/server/server-types.d.ts +16 -5
- package/dist/server/server-types.d.ts.map +1 -1
- package/dist/server/server.d.ts +4 -2
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +46 -4
- package/dist/server/server.js.map +1 -1
- package/dist/transport-codec.d.ts +4 -6
- package/dist/transport-codec.d.ts.map +1 -1
- package/dist/transport-codec.js +4 -6
- package/dist/transport-codec.js.map +1 -1
- package/package.json +1 -1
- package/src/edge-kit.ts +2 -1
- package/src/idempotency.ts +39 -23
- package/src/index.ts +1 -1
- package/src/internal/route-execution.ts +3 -0
- package/src/server/body-lane.ts +35 -0
- package/src/server/core-copies.ts +1 -1
- package/src/server/request-context.ts +12 -8
- package/src/server/respond.ts +11 -0
- package/src/server/server-types.ts +15 -5
- package/src/server/server.ts +63 -6
- package/src/transport-codec.ts +4 -6
|
@@ -17,8 +17,8 @@ export declare class TransportCodecError extends TypeError {
|
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Enforce the transport byte cap on already-read text - the same limit (and the same error) the
|
|
20
|
-
* streaming reader applies during a bounded read. Exported for callers that
|
|
21
|
-
*
|
|
20
|
+
* streaming reader applies during a bounded read. Exported for callers that need to decode text
|
|
21
|
+
* after a bounded read while preserving the text decoder's lenient UTF-8 behavior.
|
|
22
22
|
*/
|
|
23
23
|
export declare function assertTransportTextBounded(text: string, options: TransportDecodeOptions): void;
|
|
24
24
|
export declare const plainJsonCodec: TransportCodec;
|
|
@@ -46,10 +46,8 @@ export declare function readBoundedBytes(response: Response, options: TransportD
|
|
|
46
46
|
/**
|
|
47
47
|
* Decode an ALREADY-READ transport body. The counterpart to {@link decodeTransportResponse} for a
|
|
48
48
|
* caller that obtained the text through its own bounded read - notably the typed client's
|
|
49
|
-
* in-process path,
|
|
50
|
-
*
|
|
51
|
-
* nothing while costing ~23x. The byte cap is still enforced here (identical error), just after
|
|
52
|
-
* the read instead of during it.
|
|
49
|
+
* in-process path, which uses this to preserve lenient UTF-8 decoding after the shared byte-cap
|
|
50
|
+
* reader has completed.
|
|
53
51
|
*/
|
|
54
52
|
export declare function decodeTransportText(text: string, contentType: string | null, registry?: TransportCodecRegistry, options?: TransportDecodeOptions): unknown;
|
|
55
53
|
export declare function decodeTransportResponse(response: Response, registry?: TransportCodecRegistry, options?: TransportDecodeOptions): Promise<unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport-codec.d.ts","sourceRoot":"","sources":["../src/transport-codec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;IAC9B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAC9B;AAED,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIpD;AAkCD;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAU9F;AAID,eAAO,MAAM,cAAc,EAAE,cAY3B,CAAA;AAEF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;IACjC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAAA;IAC1D,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAAA;IAChD,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAAA;CACxD;AAUD,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,QAAQ,GAAE,cAA+B,GACxC,sBAAsB,CAgFxB;AAED,eAAO,MAAM,sBAAsB,EAAE,sBAEnC,CAAA;AAEF,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,KAAK,GAAE,cAA+B,EACtC,IAAI,GAAE,YAAiB,GACtB,QAAQ,CAKV;AAQD;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,UAAU,CAAC,CAkCrB;AAcD
|
|
1
|
+
{"version":3,"file":"transport-codec.d.ts","sourceRoot":"","sources":["../src/transport-codec.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;IAC9B,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CAC9B;AAED,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIpD;AAkCD;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,GAAG,IAAI,CAU9F;AAID,eAAO,MAAM,cAAc,EAAE,cAY3B,CAAA;AAEF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;IACjC,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAAA;IAC1D,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAAA;IAChD,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAAA;CACxD;AAUD,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,QAAQ,GAAE,cAA+B,GACxC,sBAAsB,CAgFxB;AAED,eAAO,MAAM,sBAAsB,EAAE,sBAEnC,CAAA;AAEF,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,KAAK,GAAE,cAA+B,EACtC,IAAI,GAAE,YAAiB,GACtB,QAAQ,CAKV;AAQD;;;;;;;;;;GAUG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,UAAU,CAAC,CAkCrB;AAcD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAAG,IAAI,EAC1B,QAAQ,GAAE,sBAA+C,EACzD,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAQT;AAED,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,QAAQ,EAClB,QAAQ,GAAE,sBAA+C,EACzD,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,OAAO,CAAC,CAQlB;AAQD,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,OAAO,EACd,KAAK,GAAE,cAA+B,GACrC,MAAM,CAER;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,QAAQ,GAAE,sBAA+C,EACzD,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAsBT"}
|
package/dist/transport-codec.js
CHANGED
|
@@ -43,8 +43,8 @@ function byteLength(text) {
|
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
45
|
* Enforce the transport byte cap on already-read text - the same limit (and the same error) the
|
|
46
|
-
* streaming reader applies during a bounded read. Exported for callers that
|
|
47
|
-
*
|
|
46
|
+
* streaming reader applies during a bounded read. Exported for callers that need to decode text
|
|
47
|
+
* after a bounded read while preserving the text decoder's lenient UTF-8 behavior.
|
|
48
48
|
*/
|
|
49
49
|
export function assertTransportTextBounded(text, options) {
|
|
50
50
|
const maxBytes = maxBytesOf(options);
|
|
@@ -233,10 +233,8 @@ async function readBoundedText(response, options) {
|
|
|
233
233
|
/**
|
|
234
234
|
* Decode an ALREADY-READ transport body. The counterpart to {@link decodeTransportResponse} for a
|
|
235
235
|
* caller that obtained the text through its own bounded read - notably the typed client's
|
|
236
|
-
* in-process path,
|
|
237
|
-
*
|
|
238
|
-
* nothing while costing ~23x. The byte cap is still enforced here (identical error), just after
|
|
239
|
-
* the read instead of during it.
|
|
236
|
+
* in-process path, which uses this to preserve lenient UTF-8 decoding after the shared byte-cap
|
|
237
|
+
* reader has completed.
|
|
240
238
|
*/
|
|
241
239
|
export function decodeTransportText(text, contentType, registry = defaultTransportCodecs, options = {}) {
|
|
242
240
|
assertBounded(text, options);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport-codec.js","sourceRoot":"","sources":["../src/transport-codec.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"transport-codec.js","sourceRoot":"","sources":["../src/transport-codec.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/edge-kit.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* exposes the one lane the fused body runner already calls, so a compact server reuses it verbatim:
|
|
9
9
|
*
|
|
10
10
|
* - {@link readBodyFramed} read + cap + proto-guard + content-type framing (JSON / urlencoded / 415)
|
|
11
|
+
* - {@link crossSiteFormRefused} the form-origin refusal for an unsafe route that reads no body
|
|
11
12
|
* - {@link capBodyBytes} the same byte cap on a handler's own reads of the raw request
|
|
12
13
|
* - {@link boundedJsonText} preflight JSON output against an exact UTF-8 byte budget
|
|
13
14
|
* - {@link renderResult} render a {@link ResponseResult} (e.g. a 413 / 415 rejection) to a `Response`
|
|
@@ -23,7 +24,7 @@
|
|
|
23
24
|
|
|
24
25
|
export { type ErrorLogDetail, emitRequestErrorLog } from "./server/bare-error-lane.ts"
|
|
25
26
|
export { assertByteLimit, capBodyBytes, DEFAULT_MAX_BODY_BYTES } from "./server/body.ts"
|
|
26
|
-
export { type FormOrigins, readBodyFramed } from "./server/body-lane.ts"
|
|
27
|
+
export { crossSiteFormRefused, type FormOrigins, readBodyFramed } from "./server/body-lane.ts"
|
|
27
28
|
export { plainError } from "./server/http.ts"
|
|
28
29
|
export { boundedJsonText, JsonByteLimitError, jsonResponse } from "./server/json-response.ts"
|
|
29
30
|
export {
|
package/src/idempotency.ts
CHANGED
|
@@ -22,6 +22,9 @@ export const DEFAULT_IDEMPOTENCY_TTL_MS = 86_400_000
|
|
|
22
22
|
/** Default lease on a key whose handler is still running, with a store that can renew it: 60 seconds. */
|
|
23
23
|
export const DEFAULT_IDEMPOTENCY_PENDING_TTL_MS = 60_000
|
|
24
24
|
|
|
25
|
+
/** Default maximum response body retained by the standalone idempotency helpers: 1 MB. */
|
|
26
|
+
export const DEFAULT_IDEMPOTENCY_MAX_RESPONSE_BYTES = 1_000_000
|
|
27
|
+
|
|
25
28
|
/** Canonical request header carrying the client-chosen idempotency key. */
|
|
26
29
|
export const DEFAULT_IDEMPOTENCY_HEADER = "idempotency-key"
|
|
27
30
|
|
|
@@ -289,16 +292,24 @@ export class IdempotencyResponseTooLargeError extends Error {
|
|
|
289
292
|
}
|
|
290
293
|
}
|
|
291
294
|
|
|
295
|
+
/**
|
|
296
|
+
* Clone and buffer a response body without exceeding the storage bound. A null body represents no
|
|
297
|
+
* bytes, even when a HEAD/304 response carries the corresponding GET representation's
|
|
298
|
+
* `Content-Length`; the body check therefore precedes the header shortcut. Oversize cancellation is
|
|
299
|
+
* intentionally fire-and-forget because a tee branch can remain pending until its sibling is read.
|
|
300
|
+
*/
|
|
292
301
|
async function boundedResponseBytes(response: Response, maxBytes: number): Promise<Uint8Array> {
|
|
302
|
+
const body = response.body
|
|
303
|
+
if (body === null) return new Uint8Array()
|
|
293
304
|
const contentLength = response.headers.get("content-length")
|
|
294
305
|
if (contentLength !== null && /^\d+$/.test(contentLength) && Number(contentLength) > maxBytes) {
|
|
295
306
|
// Replaced by a terminal error, never read: a streaming producer would otherwise stay open.
|
|
296
|
-
|
|
307
|
+
void Promise.allSettled([body.cancel()])
|
|
297
308
|
throw new IdempotencyResponseTooLargeError(maxBytes)
|
|
298
309
|
}
|
|
299
|
-
const
|
|
300
|
-
if (
|
|
301
|
-
const reader =
|
|
310
|
+
const cloneBody = response.clone().body
|
|
311
|
+
if (cloneBody === null) return new Uint8Array()
|
|
312
|
+
const reader = cloneBody.getReader()
|
|
302
313
|
const chunks: Uint8Array[] = []
|
|
303
314
|
let total = 0
|
|
304
315
|
try {
|
|
@@ -311,10 +322,11 @@ async function boundedResponseBytes(response: Response, maxBytes: number): Promi
|
|
|
311
322
|
// unread, so a streaming producer can keep the tee pending forever. This path stores no
|
|
312
323
|
// response and the caller will replace it with a terminal error, so cancel both branches.
|
|
313
324
|
const liveBody = response.body
|
|
314
|
-
await
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
325
|
+
// Do not await tee cancellation: either branch can remain pending until the other branch is
|
|
326
|
+
// consumed, but the size error is already definitive and must reach the caller promptly.
|
|
327
|
+
const cancellations = [reader.cancel()]
|
|
328
|
+
if (liveBody !== null) cancellations.push(liveBody.cancel())
|
|
329
|
+
void Promise.allSettled(cancellations)
|
|
318
330
|
throw new IdempotencyResponseTooLargeError(maxBytes)
|
|
319
331
|
}
|
|
320
332
|
chunks.push(value)
|
|
@@ -331,19 +343,21 @@ async function boundedResponseBytes(response: Response, maxBytes: number): Promi
|
|
|
331
343
|
return bytes
|
|
332
344
|
}
|
|
333
345
|
|
|
334
|
-
/**
|
|
346
|
+
/**
|
|
347
|
+
* Buffer a response into a storable form. Clones first so the live response body stays intact on
|
|
348
|
+
* success. If the body exceeds the bound, both branches may be cancelled to stop the producer and
|
|
349
|
+
* the caller must discard or replace the response. Unless a bound is supplied, at most
|
|
350
|
+
* {@link DEFAULT_IDEMPOTENCY_MAX_RESPONSE_BYTES} are retained.
|
|
351
|
+
*/
|
|
335
352
|
export async function serializeResponse(
|
|
336
353
|
response: Response,
|
|
337
354
|
options: { readonly maxBytes?: number } = {},
|
|
338
355
|
): Promise<StoredResponse> {
|
|
339
|
-
const maxBytes = options.maxBytes
|
|
340
|
-
if (
|
|
356
|
+
const maxBytes = options.maxBytes ?? DEFAULT_IDEMPOTENCY_MAX_RESPONSE_BYTES
|
|
357
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 0) {
|
|
341
358
|
throw new RangeError("idempotency: max response bytes must be a non-negative integer")
|
|
342
359
|
}
|
|
343
|
-
const bytes =
|
|
344
|
-
maxBytes === undefined
|
|
345
|
-
? new Uint8Array(await response.clone().arrayBuffer())
|
|
346
|
-
: await boundedResponseBytes(response, maxBytes)
|
|
360
|
+
const bytes = await boundedResponseBytes(response, maxBytes)
|
|
347
361
|
return {
|
|
348
362
|
status: response.status,
|
|
349
363
|
headers: replaySafeHeaders(response.headers),
|
|
@@ -351,7 +365,10 @@ export async function serializeResponse(
|
|
|
351
365
|
}
|
|
352
366
|
}
|
|
353
367
|
|
|
354
|
-
/**
|
|
368
|
+
/**
|
|
369
|
+
* Rebuild a live response from storage, stamping the replay marker header. Unless a bound is
|
|
370
|
+
* supplied, stored bodies larger than {@link DEFAULT_IDEMPOTENCY_MAX_RESPONSE_BYTES} are rejected.
|
|
371
|
+
*/
|
|
355
372
|
export function responseFromStored(
|
|
356
373
|
stored: StoredResponse,
|
|
357
374
|
options: { readonly maxBytes?: number } = {},
|
|
@@ -360,13 +377,12 @@ export function responseFromStored(
|
|
|
360
377
|
throw new TypeError("idempotency: corrupt stored response status")
|
|
361
378
|
}
|
|
362
379
|
const decodedLength = base64DecodedLength(stored.body)
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
}
|
|
380
|
+
const maxBytes = options.maxBytes ?? DEFAULT_IDEMPOTENCY_MAX_RESPONSE_BYTES
|
|
381
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 0) {
|
|
382
|
+
throw new RangeError("idempotency: max response bytes must be a non-negative safe integer")
|
|
383
|
+
}
|
|
384
|
+
if (decodedLength > maxBytes) {
|
|
385
|
+
throw new IdempotencyResponseTooLargeError(maxBytes)
|
|
370
386
|
}
|
|
371
387
|
const headers = new Headers(replaySafeHeaders(stored.headers) as [string, string][])
|
|
372
388
|
headers.set(IDEMPOTENT_REPLAY_HEADER, "1")
|
package/src/index.ts
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* read its own package.json at runtime. `scripts/version.ts` rewrites it on every release bump and
|
|
17
17
|
* `check:publish` asserts it equals `@nifrajs/core`'s package version.
|
|
18
18
|
*/
|
|
19
|
-
export const VERSION = "5.
|
|
19
|
+
export const VERSION = "5.13.0" as const
|
|
20
20
|
|
|
21
21
|
export type Version = typeof VERSION
|
|
22
22
|
|
|
@@ -325,6 +325,9 @@ export interface RouteEntry {
|
|
|
325
325
|
readonly onError: ReadonlyArray<RawErrorHandler>
|
|
326
326
|
/** Registration-specialized hook shape: a route whose only lifecycle steps are derive, before and after hooks. */
|
|
327
327
|
readonly lifecycleHookLane: "hooks" | undefined
|
|
328
|
+
/** An unsafe method with no body schema: no lane reads a body to refuse a cross-site form, so the
|
|
329
|
+
* dispatchers refuse it before the lanes run. */
|
|
330
|
+
readonly formOriginGuard: boolean
|
|
328
331
|
/** Wraps the matched route lifecycle. Empty for the common no-around path. */
|
|
329
332
|
readonly around: ReadonlyArray<RawAround>
|
|
330
333
|
/** The single immutable execution decision consumed by portable, Node-direct, and Bun-native paths. */
|
package/src/server/body-lane.ts
CHANGED
|
@@ -236,6 +236,41 @@ function formOriginAllowed(source: RequestSource, formOrigins: FormOrigins | und
|
|
|
236
236
|
: formOrigins.includes(origin)
|
|
237
237
|
}
|
|
238
238
|
|
|
239
|
+
/** A route that needs {@link crossSiteFormRefused} ahead of its lanes: an unsafe method with no
|
|
240
|
+
* `schema.body`. A body schema reads its body through {@link readBodyFramed}, which refuses a
|
|
241
|
+
* cross-site form itself; a route without one reads nothing, so nothing else would. */
|
|
242
|
+
export const guardsBodylessForm = (method: string, hasBodySchema: boolean): boolean =>
|
|
243
|
+
!hasBodySchema && !/^(?:GET|HEAD|OPTIONS|TRACE|QUERY)$/i.test(method)
|
|
244
|
+
|
|
245
|
+
// Schemes a browser keeps in its HTTP-auth cache and re-attaches to a credentialed cross-site request
|
|
246
|
+
// on its own, so a page can send one with no preflight. Any other `Authorization` value has to be set
|
|
247
|
+
// by script, and a cross-origin script cannot set it without a preflight that CORS has judged.
|
|
248
|
+
const BROWSER_MANAGED_AUTH = /^(?:basic|digest|negotiate|ntlm)\b/i
|
|
249
|
+
|
|
250
|
+
/** Whether a request is a cross-site post that {@link readBodyFramed} would refuse, or one a page can
|
|
251
|
+
* send the same way: a form media type, or no content type at all (`fetch` with `no-cors`). A request
|
|
252
|
+
* with no content type that carries an `Authorization` header other than a browser-managed scheme
|
|
253
|
+
* (Basic, Digest, Negotiate, NTLM) passes: script-set, it forced a preflight, so the app's CORS policy
|
|
254
|
+
* has already judged its origin. It decides on the cheapest header first: a request without an
|
|
255
|
+
* `Origin` (any non-browser client) costs one lookup, and a browser's own-origin post stops at
|
|
256
|
+
* `Sec-Fetch-Site` before the URL is parsed. */
|
|
257
|
+
export const crossSiteFormRefused = (
|
|
258
|
+
source: RequestSource,
|
|
259
|
+
formOrigins: FormOrigins | undefined,
|
|
260
|
+
): boolean => {
|
|
261
|
+
const origin = headerOf(source, "origin")
|
|
262
|
+
if (origin === null || headerOf(source, "sec-fetch-site") === "same-origin") return false
|
|
263
|
+
const type = headerOf(source, "content-type") ?? ""
|
|
264
|
+
const authorization = type === "" ? headerOf(source, "authorization") : null
|
|
265
|
+
return (
|
|
266
|
+
(type === ""
|
|
267
|
+
? authorization === null || BROWSER_MANAGED_AUTH.test(authorization)
|
|
268
|
+
: isFormMediaType(type)) &&
|
|
269
|
+
!source.url.startsWith(`${origin}/`) &&
|
|
270
|
+
!formOriginAllowed(source, formOrigins)
|
|
271
|
+
)
|
|
272
|
+
}
|
|
273
|
+
|
|
239
274
|
/**
|
|
240
275
|
* The shared content-type dispatcher around the JSON and urlencoded lanes. A `bodySchema` branded
|
|
241
276
|
* with {@link SCHEMA_BODY_READER} takes every other media type; JSON and urlencoded bodies keep
|
|
@@ -26,7 +26,7 @@ if (!copies.includes(here) && copies.push(here) > 1) {
|
|
|
26
26
|
|
|
27
27
|
/** This copy's version: a literal like the package root's `VERSION` (no fs on the edge), which
|
|
28
28
|
* `scripts/version.ts` rewrites on every release and `check:publish` asserts. */
|
|
29
|
-
const COPY_VERSION = "5.
|
|
29
|
+
const COPY_VERSION = "5.13.0"
|
|
30
30
|
|
|
31
31
|
/** Record this copy's version beside its URL. Called by each `server()` behind the development guard,
|
|
32
32
|
* so a production bundle drops it with the version; a copy that built a server has recorded one. */
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* sits below the server module in the graph.
|
|
6
6
|
*/
|
|
7
7
|
import type { RequestBudget } from "../budget.ts"
|
|
8
|
-
import { markResidentBody } from "../mount.ts"
|
|
8
|
+
import { markResidentBody, residentBodiesRecorded } from "../mount.ts"
|
|
9
9
|
import { applyTransportCap, readBoundedBytes } from "./body.ts"
|
|
10
10
|
import { readBoundedJsonSource } from "./body-lane.ts"
|
|
11
11
|
import type { Platform } from "./context.ts"
|
|
@@ -165,6 +165,8 @@ function responseTextContentType(): string {
|
|
|
165
165
|
/** `c.text`'s own default, unchanged: the explicit one nifra has always declared when the caller
|
|
166
166
|
* passes no headers of their own. */
|
|
167
167
|
const TEXT_CONTENT_TYPE = "text/plain; charset=utf-8"
|
|
168
|
+
const TEXT_RESPONSE_HEADERS = { "content-type": TEXT_CONTENT_TYPE }
|
|
169
|
+
const TEXT_RESPONSE_INIT: ResponseInit = { headers: TEXT_RESPONSE_HEADERS }
|
|
168
170
|
|
|
169
171
|
/** Where a serving adapter that shares one platform across requests leaves its socket-peer lookup.
|
|
170
172
|
* `c.clientIp` calls it with the request when a handler reads the address, so a request whose
|
|
@@ -439,13 +441,15 @@ export class RequestContext implements RawContext {
|
|
|
439
441
|
}
|
|
440
442
|
}
|
|
441
443
|
// Default to text/plain; if the caller passes their own headers, they own the content-type.
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
new Response(
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
444
|
+
const response =
|
|
445
|
+
i?.headers !== undefined
|
|
446
|
+
? new Response(body, i)
|
|
447
|
+
: new Response(
|
|
448
|
+
body,
|
|
449
|
+
i === undefined ? TEXT_RESPONSE_INIT : { ...i, headers: TEXT_RESPONSE_HEADERS },
|
|
450
|
+
)
|
|
451
|
+
const resident = residentText(response, body)
|
|
452
|
+
return residentBodiesRecorded ? markResidentBody(resident) : resident
|
|
449
453
|
}
|
|
450
454
|
|
|
451
455
|
get query(): unknown {
|
package/src/server/respond.ts
CHANGED
|
@@ -613,6 +613,17 @@ export function fusedRespond(
|
|
|
613
613
|
unstamped = false,
|
|
614
614
|
): Response {
|
|
615
615
|
const set = ctx[CONTEXT_SET]()
|
|
616
|
+
if (
|
|
617
|
+
set === undefined &&
|
|
618
|
+
statics === undefined &&
|
|
619
|
+
!tagResponseBody &&
|
|
620
|
+
result instanceof Response &&
|
|
621
|
+
!isResponseResult(result) &&
|
|
622
|
+
!responseBodyUsed(result)
|
|
623
|
+
) {
|
|
624
|
+
if (!isBodylessStatus(result.status)) return result
|
|
625
|
+
return normalizeBodylessResponse(result, unstamped ? undefined : ctx[CONTEXT_REQUEST])
|
|
626
|
+
}
|
|
616
627
|
const request = unstamped ? undefined : ctx[CONTEXT_REQUEST]
|
|
617
628
|
if (set === undefined)
|
|
618
629
|
return fusedRespondNoSet(result, tagResponseBody, statics, unstamped, request)
|
|
@@ -64,11 +64,19 @@ export interface ServerOptions {
|
|
|
64
64
|
*/
|
|
65
65
|
readonly protoPoisoning?: "reject" | "strip" | "ignore"
|
|
66
66
|
/**
|
|
67
|
-
* Other sites whose HTML forms may post to a
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
67
|
+
* Other sites whose HTML forms may post to a route: exact origins, or a function that receives the
|
|
68
|
+
* `Origin`. A urlencoded, multipart or `text/plain` body is one a form on any site can send with the
|
|
69
|
+
* visitor's cookies and no preflight, so one whose `Origin` names another site is refused with `403`
|
|
70
|
+
* before it is read. A route without a body schema refuses the same sites' unsafe requests that carry
|
|
71
|
+
* no content type too, which `fetch` with `no-cors` sends; one with a script-set `Authorization` header
|
|
72
|
+
* passes, since a browser preflights it, but `Basic`, `Digest`, `Negotiate` and `NTLM` do not, because
|
|
73
|
+
* a browser re-sends those from its auth cache without one. Same-origin posts and requests without an `Origin`, such as
|
|
74
|
+
* server-to-server calls, pass. JSON is not affected: a browser preflights it, so CORS decides.
|
|
75
|
+
* The origins a `cors()` list or predicate and a `csrf({ origins })` list name are trusted as well,
|
|
76
|
+
* so a frontend those already allow needs no second list here; `cors()` with `"*"` adds none. That
|
|
77
|
+
* trust is for form posts to this server's own routes only: a mounted or grouped server keeps its own
|
|
78
|
+
* policy, so a parent that must accept the same sites sets them in its own `formOrigins`, and a web
|
|
79
|
+
* page action checks the origin against the backend's `allowedOrigins`, not this list.
|
|
72
80
|
*/
|
|
73
81
|
readonly formOrigins?: ReadonlyArray<string> | ((origin: string) => boolean)
|
|
74
82
|
/**
|
|
@@ -396,6 +404,8 @@ export interface RunningServer {
|
|
|
396
404
|
readonly hostname: string
|
|
397
405
|
readonly pendingRequests: number
|
|
398
406
|
stop(closeActiveConnections?: boolean): void
|
|
407
|
+
/** `await using server = app.listen(3000)`: the app's graceful `stop()` with default options, not Bun's raw one. Waits for a shutdown already under way. */
|
|
408
|
+
[Symbol.asyncDispose](): Promise<void>
|
|
399
409
|
/** Bun's native topic broadcast, present on the Bun `Server` handle. `app.publish` delegates to it
|
|
400
410
|
* in native-pubsub mode; absent on other runtimes' running-server views. */
|
|
401
411
|
publish?(topic: string, data: string | ArrayBufferView | ArrayBuffer): number
|
package/src/server/server.ts
CHANGED
|
@@ -88,7 +88,7 @@ import {
|
|
|
88
88
|
type RawBodyReaders,
|
|
89
89
|
UNLIMITED_BODY_BYTES,
|
|
90
90
|
} from "./body.ts"
|
|
91
|
-
import type
|
|
91
|
+
import { crossSiteFormRefused, type FormOrigins, guardsBodylessForm } from "./body-lane.ts"
|
|
92
92
|
import {
|
|
93
93
|
type ClientIpTrust,
|
|
94
94
|
NIFRA_PLATFORM_CLIENT_IP_DERIVED,
|
|
@@ -261,6 +261,7 @@ export type MaybePromise<T> = T | Promise<T>
|
|
|
261
261
|
// ordinary registered routes on its native table and send unmatched OPTIONS requests through the
|
|
262
262
|
// normal fetch fallback where the hook still runs.
|
|
263
263
|
const BUN_NATIVE_REQUEST_SAFE = Symbol.for("@nifrajs/core/bun-native-request-safe")
|
|
264
|
+
const TRUSTED_ORIGINS = Symbol.for("nifra.trustedOrigins")
|
|
264
265
|
|
|
265
266
|
/**
|
|
266
267
|
* Internal request view. A real Web `Request` already satisfies this shape, so Web/edge runtimes pass
|
|
@@ -691,6 +692,17 @@ const UNROUTED_CHAR = /[^!$%&'()*+,\-./0-9:;=?@A-Z[\]_a-z|~]/
|
|
|
691
692
|
const unroutedParam = (value: string | undefined): boolean =>
|
|
692
693
|
value !== undefined && (value === "." || value === ".." || UNROUTED_CHAR.test(value))
|
|
693
694
|
|
|
695
|
+
/** Native query-schema routes can pass this search substring into RequestContext directly instead of
|
|
696
|
+
* building both pathname and search with the portable URL helper. Keep fragment handling identical
|
|
697
|
+
* to `urlPartsOf`; in-process Requests can retain a fragment even though network request targets do not. */
|
|
698
|
+
function searchOfNativeRequest(url: string): string {
|
|
699
|
+
const question = url.indexOf("?")
|
|
700
|
+
const fragment = url.indexOf("#")
|
|
701
|
+
return question < 0 || (fragment >= 0 && question > fragment)
|
|
702
|
+
? ""
|
|
703
|
+
: url.slice(question, fragment < 0 ? undefined : fragment)
|
|
704
|
+
}
|
|
705
|
+
|
|
694
706
|
function hasUnroutedParam(params: Record<string, string>): boolean {
|
|
695
707
|
for (const key in params) {
|
|
696
708
|
if (unroutedParam(params[key])) return true
|
|
@@ -1488,7 +1500,7 @@ export class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext, Hook
|
|
|
1488
1500
|
| undefined
|
|
1489
1501
|
private readonly maxBodyBytes: number
|
|
1490
1502
|
private readonly protoPoisoning: "reject" | "strip" | "ignore"
|
|
1491
|
-
private
|
|
1503
|
+
private formOrigins: FormOrigins | undefined
|
|
1492
1504
|
/** `trustBodyFraming`: mark every `app.fetch` request as runtime-framed (see ServerOptions). */
|
|
1493
1505
|
private readonly trustBodyFraming: boolean
|
|
1494
1506
|
private readonly validateHost: boolean
|
|
@@ -1538,6 +1550,8 @@ export class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext, Hook
|
|
|
1538
1550
|
/** App-wide validation-error fallback; a route's own `schema.onValidationError` takes precedence. */
|
|
1539
1551
|
private readonly defaultOnValidationError?: RouteSchema["onValidationError"]
|
|
1540
1552
|
private bunServer: RunningServer | undefined
|
|
1553
|
+
// The shutdown `stop()` last began, so a handle disposed mid-shutdown waits for it rather than for nothing.
|
|
1554
|
+
private stopRun: Promise<void> | undefined
|
|
1541
1555
|
// Bun's `pendingRequests` leaves out upgraded sockets, so `stop()` closes these itself.
|
|
1542
1556
|
private bunSockets: Set<{ close(code?: number): void }> | undefined
|
|
1543
1557
|
private signalHandler: (() => void) | undefined
|
|
@@ -2322,6 +2336,15 @@ export class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext, Hook
|
|
|
2322
2336
|
}
|
|
2323
2337
|
this[INSTALL_RESPONSE_OBSERVER](responseObserver as ResponseObserverRuntime)
|
|
2324
2338
|
}
|
|
2339
|
+
// `cors()` and `csrf()` name the origins they trust; a form post from one of them is the app's own
|
|
2340
|
+
// frontend, so it joins `formOrigins` rather than being listed twice.
|
|
2341
|
+
const trusted: unknown = Reflect.get(arg, TRUSTED_ORIGINS)
|
|
2342
|
+
if (typeof trusted === "function") {
|
|
2343
|
+
const listed = this.formOrigins
|
|
2344
|
+
this.formOrigins = (origin) =>
|
|
2345
|
+
(typeof listed === "function" ? listed(origin) : listed?.includes(origin)) === true ||
|
|
2346
|
+
trusted(origin) === true
|
|
2347
|
+
}
|
|
2325
2348
|
if (arg.onRequest !== undefined) {
|
|
2326
2349
|
this.assertConfigurable("onRequest()")
|
|
2327
2350
|
this.onRequestHooks.push(arg.onRequest as RawOnRequest)
|
|
@@ -2823,6 +2846,8 @@ export class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext, Hook
|
|
|
2823
2846
|
handler: (context: never) => unknown,
|
|
2824
2847
|
): CatalogRoute {
|
|
2825
2848
|
const staticResponse = staticResponseDefinition(handler)
|
|
2849
|
+
// A handler carrying this marker checks the Origin itself (web page actions), so the default stays out.
|
|
2850
|
+
const ownsFormOrigin = Reflect.get(handler, Symbol.for("nifra.route.ownsFormOrigin")) === true
|
|
2826
2851
|
schema = withTextSlots(schema)
|
|
2827
2852
|
// Route provenance for the CLI's capability walk, which sets NIFRA_ROUTE_SITES while it loads the
|
|
2828
2853
|
// app: the module that registered the route, read where a static scan cannot see the path.
|
|
@@ -2982,6 +3007,7 @@ export class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext, Hook
|
|
|
2982
3007
|
afterHandle: aftersSnapshot,
|
|
2983
3008
|
onError: onErrorSnapshot,
|
|
2984
3009
|
lifecycleHookLane: lanes.lifecycleHookLane,
|
|
3010
|
+
formOriginGuard: !ownsFormOrigin && guardsBodylessForm(method, schema?.body !== undefined),
|
|
2985
3011
|
around: [...this.aroundHooks],
|
|
2986
3012
|
execution,
|
|
2987
3013
|
program,
|
|
@@ -4807,6 +4833,9 @@ export class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext, Hook
|
|
|
4807
4833
|
onTimeout: () => T,
|
|
4808
4834
|
webFast: boolean,
|
|
4809
4835
|
): MaybePromise<T> {
|
|
4836
|
+
if (entry.formOriginGuard && crossSiteFormRefused(source, this.formOrigins)) {
|
|
4837
|
+
return wrapResponse(plainError(403, "forbidden_origin"))
|
|
4838
|
+
}
|
|
4810
4839
|
// The route's transport byte cap: one property write here; the capped shadowing of direct
|
|
4811
4840
|
// `c.req` body readers happens lazily at `c.req` access (`applyTransportCap`), so a route that
|
|
4812
4841
|
// never direct-reads pays nothing. Framework readers bypass the shadow (`rawBodySourceOf`) and
|
|
@@ -7335,10 +7364,11 @@ export class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext, Hook
|
|
|
7335
7364
|
entry.schema?.body === undefined || entry.program.authBeforeValidation
|
|
7336
7365
|
? entry.bodyLimit
|
|
7337
7366
|
: undefined
|
|
7367
|
+
const hasQuerySchema = entry.schema?.query !== undefined
|
|
7338
7368
|
// The complete plan already preserves general validation, hooks, recovery, around, and ledgers.
|
|
7339
7369
|
// When native admission is safe, use it directly even if the route has no closed-shape fusion.
|
|
7340
7370
|
// Idempotency still needs runMatched's request preparation and is excluded from the table.
|
|
7341
|
-
const
|
|
7371
|
+
const unguarded: FusedWebRunner | undefined =
|
|
7342
7372
|
fused ??
|
|
7343
7373
|
(signal && budget
|
|
7344
7374
|
? (source, params, search, activeSignal, activeBudget, platform, nativeContext) =>
|
|
@@ -7356,6 +7386,13 @@ export class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext, Hook
|
|
|
7356
7386
|
this.wrapWebResponse,
|
|
7357
7387
|
)
|
|
7358
7388
|
: undefined)
|
|
7389
|
+
const inner: FusedWebRunner | undefined =
|
|
7390
|
+
unguarded === undefined || !entry.formOriginGuard
|
|
7391
|
+
? unguarded
|
|
7392
|
+
: (source, params, search, fusedSignal, fusedBudget, platform, nativeContext) =>
|
|
7393
|
+
crossSiteFormRefused(source, this.formOrigins)
|
|
7394
|
+
? this.wrapWebResponse(plainError(403, "forbidden_origin"))
|
|
7395
|
+
: unguarded(source, params, search, fusedSignal, fusedBudget, platform, nativeContext)
|
|
7359
7396
|
// The cap is never marked on a GET or HEAD, the only methods a GET or HEAD slot is handed, so those
|
|
7360
7397
|
// slots skip the wrapper and its read of the method on every request.
|
|
7361
7398
|
const capped: FusedWebRunner | undefined =
|
|
@@ -7377,7 +7414,15 @@ export class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext, Hook
|
|
|
7377
7414
|
): MaybePromise<Response> => {
|
|
7378
7415
|
let outcome: MaybePromise<Response>
|
|
7379
7416
|
try {
|
|
7380
|
-
outcome = capped!(
|
|
7417
|
+
outcome = capped!(
|
|
7418
|
+
request,
|
|
7419
|
+
params,
|
|
7420
|
+
hasQuerySchema ? searchOfNativeRequest(request.url) : undefined,
|
|
7421
|
+
signal!,
|
|
7422
|
+
budget!,
|
|
7423
|
+
peer,
|
|
7424
|
+
true,
|
|
7425
|
+
)
|
|
7381
7426
|
} catch (err) {
|
|
7382
7427
|
// A synchronous render throw, as in runMatchedLanes.
|
|
7383
7428
|
outcome = this.contextlessBareError(
|
|
@@ -7599,7 +7644,7 @@ export class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext, Hook
|
|
|
7599
7644
|
if (
|
|
7600
7645
|
mayUseStaticResponse &&
|
|
7601
7646
|
staticResponse !== undefined &&
|
|
7602
|
-
(method === "GET" || method === "HEAD") &&
|
|
7647
|
+
(method === "GET" || method === "HEAD" || method === "POST") &&
|
|
7603
7648
|
// Bun 1.3 can misframe null-body status codes in its native static table.
|
|
7604
7649
|
staticResponse.status !== 204 &&
|
|
7605
7650
|
staticResponse.status !== 205 &&
|
|
@@ -7882,6 +7927,8 @@ export class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext, Hook
|
|
|
7882
7927
|
},
|
|
7883
7928
|
})) as unknown as RunningServer
|
|
7884
7929
|
this.bunServer = running
|
|
7930
|
+
running[Symbol.asyncDispose] = () =>
|
|
7931
|
+
this.bunServer === running ? this.stop() : (this.stopRun ?? Promise.resolve())
|
|
7885
7932
|
// Bind `app.publish` to Bun's native broadcast now that the server handle exists. Guarded on the
|
|
7886
7933
|
// method's presence so a runtime whose handle lacks it simply keeps the registry path. Cleared
|
|
7887
7934
|
// first: a mounted app may have gained a WebSocket route since an earlier `listen()`.
|
|
@@ -7910,7 +7957,17 @@ export class Server<R extends Registry = EmptyRegistry, Ctx = EmptyContext, Hook
|
|
|
7910
7957
|
* hooks after the drain. Open WebSockets get a 1001 close when the drain starts and the same
|
|
7911
7958
|
* window to finish it; a socket opened after `stop()` began is closed at once.
|
|
7912
7959
|
*/
|
|
7913
|
-
|
|
7960
|
+
stop(options: StopOptions = {}): Promise<void> {
|
|
7961
|
+
const owns = this.bunServer !== undefined
|
|
7962
|
+
const run = this.stopListener(options)
|
|
7963
|
+
if (owns) this.stopRun = run
|
|
7964
|
+
return run
|
|
7965
|
+
}
|
|
7966
|
+
|
|
7967
|
+
private async stopListener({
|
|
7968
|
+
drainMs = DEFAULT_DRAIN_MS,
|
|
7969
|
+
delayMs = 0,
|
|
7970
|
+
}: StopOptions): Promise<void> {
|
|
7914
7971
|
const onSignal = this.signalHandler
|
|
7915
7972
|
if (onSignal !== undefined) {
|
|
7916
7973
|
this.signalHandler = undefined
|
package/src/transport-codec.ts
CHANGED
|
@@ -61,8 +61,8 @@ function byteLength(text: string): number {
|
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* Enforce the transport byte cap on already-read text - the same limit (and the same error) the
|
|
64
|
-
* streaming reader applies during a bounded read. Exported for callers that
|
|
65
|
-
*
|
|
64
|
+
* streaming reader applies during a bounded read. Exported for callers that need to decode text
|
|
65
|
+
* after a bounded read while preserving the text decoder's lenient UTF-8 behavior.
|
|
66
66
|
*/
|
|
67
67
|
export function assertTransportTextBounded(text: string, options: TransportDecodeOptions): void {
|
|
68
68
|
const maxBytes = maxBytesOf(options)
|
|
@@ -278,10 +278,8 @@ async function readBoundedText(
|
|
|
278
278
|
/**
|
|
279
279
|
* Decode an ALREADY-READ transport body. The counterpart to {@link decodeTransportResponse} for a
|
|
280
280
|
* caller that obtained the text through its own bounded read - notably the typed client's
|
|
281
|
-
* in-process path,
|
|
282
|
-
*
|
|
283
|
-
* nothing while costing ~23x. The byte cap is still enforced here (identical error), just after
|
|
284
|
-
* the read instead of during it.
|
|
281
|
+
* in-process path, which uses this to preserve lenient UTF-8 decoding after the shared byte-cap
|
|
282
|
+
* reader has completed.
|
|
285
283
|
*/
|
|
286
284
|
export function decodeTransportText(
|
|
287
285
|
text: string,
|