@nifrajs/node 3.5.0 → 4.0.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/README.md CHANGED
@@ -59,6 +59,11 @@ create a local TOCTOU race. Mutable or attacker-writable static trees are theref
59
59
  adapter's guarantee. Store user-controlled files outside the static root and serve them through
60
60
  an application or object-storage path with its own validation policy.
61
61
 
62
+ Every file carries a strong `ETag` (from mtime and size), `Last-Modified`, and
63
+ `Accept-Ranges: bytes`. `If-None-Match` and `If-Modified-Since` get a bodyless 304; a single
64
+ `Range` on GET gets 206 (or 416 when unsatisfiable), gated by `If-Range`. Multi-range requests get
65
+ the whole file.
66
+
62
67
  ## Graceful shutdown on signals
63
68
 
64
69
  Opt in to SIGTERM/SIGINT handling so a `docker stop` / Ctrl-C drains in-flight requests
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Whether `target` - an absolute URL or an origin-form `/path?query` - may hold a `.` or `..`
3
+ * segment, raw or percent-encoded, or a backslash: what a WHATWG parser would rewrite. Never false
4
+ * when the path has one. It can be true when only the query looks like one (`?next=/../x`):
5
+ * resolving that target leaves its path and query as they are, apart from the characters a parser
6
+ * always percent-encodes.
7
+ */
8
+ export declare function hasDotSegment(target: string): boolean;
9
+ /**
10
+ * `target` with its dot segments resolved and its backslashes read as `/`, by the platform's own
11
+ * WHATWG parser. An origin-form target stays origin-form (the fragment, which no client sends,
12
+ * dropped); an absolute URL comes back absolute. The parser also percent-encodes what it always
13
+ * encodes, which is what Bun and workerd deliver for the same request. A target that is neither -
14
+ * `*`, or text no URL parser accepts - comes back as it arrived: there is no path to resolve.
15
+ */
16
+ export declare function resolveDotSegments(target: string): string;
17
+ //# sourceMappingURL=request-target.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-target.d.ts","sourceRoot":"","sources":["../../src/generated/request-target.ts"],"names":[],"mappings":"AAsBA;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAGrD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOzD"}
@@ -0,0 +1,46 @@
1
+ // Generated by scripts/gen-node-outcome.ts - edit packages/core/src/server/request-target.ts instead.
2
+ // Copied so @nifrajs/node resolves a raw target exactly as core does, without depending on it.
3
+ /**
4
+ * Dot segments in a request target, resolved the way a WHATWG URL parser resolves them.
5
+ *
6
+ * Bun and workerd hand an app a request whose URL is already parsed: a client that sends
7
+ * `/users/../posts`, `/users/%2e%2e/posts` or `/users/..\posts` is asking for `/posts`, and that
8
+ * is the URL the app sees. Node's `IncomingMessage.url` and Deno's `Request.url` carry the target
9
+ * exactly as it was sent. Routing the raw text on those runtimes and the parsed text on the others
10
+ * sends one request to two different handlers - with two different sets of guards - depending on
11
+ * where the app runs. So a raw target is resolved before anything reads it, and every runtime routes
12
+ * the same path.
13
+ *
14
+ * No imports: `@nifrajs/node` carries a generated copy of this module, since it never depends on
15
+ * core at runtime.
16
+ */
17
+ // A `.` or `..` segment (`%2e` counts as a dot, in either case), or a backslash, which a WHATWG
18
+ // parser reads as a `/` in an http(s) path.
19
+ const DOT_SEGMENT = /\\|\/(?:\.|%2e){1,2}(?:[/?#]|$)/i;
20
+ /**
21
+ * Whether `target` - an absolute URL or an origin-form `/path?query` - may hold a `.` or `..`
22
+ * segment, raw or percent-encoded, or a backslash: what a WHATWG parser would rewrite. Never false
23
+ * when the path has one. It can be true when only the query looks like one (`?next=/../x`):
24
+ * resolving that target leaves its path and query as they are, apart from the characters a parser
25
+ * always percent-encodes.
26
+ */
27
+ export function hasDotSegment(target) {
28
+ // One regex pass: measured faster on Node and Deno than substring scans that gate it.
29
+ return DOT_SEGMENT.test(target);
30
+ }
31
+ /**
32
+ * `target` with its dot segments resolved and its backslashes read as `/`, by the platform's own
33
+ * WHATWG parser. An origin-form target stays origin-form (the fragment, which no client sends,
34
+ * dropped); an absolute URL comes back absolute. The parser also percent-encodes what it always
35
+ * encodes, which is what Bun and workerd deliver for the same request. A target that is neither -
36
+ * `*`, or text no URL parser accepts - comes back as it arrived: there is no path to resolve.
37
+ */
38
+ export function resolveDotSegments(target) {
39
+ if (target.charCodeAt(0) === 47 /* / */) {
40
+ // Appended to an origin, not resolved against one: `//host/..` must stay a path on this origin.
41
+ const url = new URL(`http://localhost${target}`);
42
+ return url.pathname + url.search;
43
+ }
44
+ return URL.canParse(target) ? new URL(target).href : target;
45
+ }
46
+ //# sourceMappingURL=request-target.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-target.js","sourceRoot":"","sources":["../../src/generated/request-target.ts"],"names":[],"mappings":"AAAA,sGAAsG;AACtG,+FAA+F;AAE/F;;;;;;;;;;;;;GAaG;AAEH,gGAAgG;AAChG,4CAA4C;AAC5C,MAAM,WAAW,GAAG,kCAAkC,CAAA;AAEtD;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,sFAAsF;IACtF,OAAO,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AACjC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,IAAI,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,CAAC;QACxC,gGAAgG;QAChG,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAA;QAChD,OAAO,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAA;IAClC,CAAC;IACD,OAAO,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAA;AAC7D,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { type IncomingMessage } from "node:http";
2
+ import type { TlsOptions } from "node:tls";
2
3
  /** The runtime platform a nifra app accepts as `fetch`'s 2nd arg - here, the observed socket peer. */
3
4
  interface NodePlatform {
4
5
  readonly clientIp?: string;
@@ -80,11 +81,18 @@ export interface ServeOptions {
80
81
  /**
81
82
  * Protocol used when the adapter constructs `Request.url`.
82
83
  *
83
- * `@nifrajs/node` creates a plain Node `http` server, so the safe default is `"http"`. Deployments behind
84
- * TLS termination can set `"https"` (or a trusted infra-aware function) so app code that reads
84
+ * The default is `"https"` when {@link ServeOptions.tls} is set and `"http"` otherwise. Deployments
85
+ * behind TLS termination can set `"https"` (or a trusted infra-aware function) so app code that reads
85
86
  * `request.url` sees the public scheme. Forwarded headers are not trusted implicitly.
86
87
  */
87
88
  readonly protocol?: RequestProtocolOption;
89
+ /**
90
+ * Serve HTTPS directly, with no proxy in front: `{ cert, key }` as PEM text or the files' bytes
91
+ * (`readFileSync("cert.pem")`), plus any other `node:tls` server option (`passphrase`, `ca`,
92
+ * `requestCert` for client certificates, `minVersion`, `SNICallback`, ...). Unset, the server speaks
93
+ * plain HTTP, which is what a proxy or platform that terminates TLS expects.
94
+ */
95
+ readonly tls?: TlsOptions;
88
96
  /** Reject requests whose normalized Host authority is not in this allowlist or callback result. */
89
97
  readonly allowedHosts?: readonly string[] | ((host: string) => boolean);
90
98
  /** Use this validated authority when constructing Request.url, ignoring the inbound Host value. */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}