nlcurl 0.5.0 → 0.7.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.
Files changed (178) hide show
  1. package/README.md +41 -8
  2. package/dist/cache/store.d.ts +89 -0
  3. package/dist/cache/store.d.ts.map +1 -0
  4. package/dist/cache/store.js +402 -0
  5. package/dist/cache/store.js.map +1 -0
  6. package/dist/cache/types.d.ts +101 -0
  7. package/dist/cache/types.d.ts.map +1 -0
  8. package/dist/cache/types.js +2 -0
  9. package/dist/cache/types.js.map +1 -0
  10. package/dist/cookies/jar.d.ts +20 -0
  11. package/dist/cookies/jar.d.ts.map +1 -1
  12. package/dist/cookies/jar.js +64 -10
  13. package/dist/cookies/jar.js.map +1 -1
  14. package/dist/cookies/parser.d.ts +2 -10
  15. package/dist/cookies/parser.d.ts.map +1 -1
  16. package/dist/cookies/parser.js +49 -2
  17. package/dist/cookies/parser.js.map +1 -1
  18. package/dist/cookies/psl-data.d.ts +12 -0
  19. package/dist/cookies/psl-data.d.ts.map +1 -0
  20. package/dist/cookies/psl-data.js +10166 -0
  21. package/dist/cookies/psl-data.js.map +1 -0
  22. package/dist/cookies/public-suffix.d.ts +37 -0
  23. package/dist/cookies/public-suffix.d.ts.map +1 -0
  24. package/dist/cookies/public-suffix.js +140 -0
  25. package/dist/cookies/public-suffix.js.map +1 -0
  26. package/dist/core/client.js +4 -0
  27. package/dist/core/client.js.map +1 -1
  28. package/dist/core/request.d.ts +73 -3
  29. package/dist/core/request.d.ts.map +1 -1
  30. package/dist/core/response.d.ts +22 -0
  31. package/dist/core/response.d.ts.map +1 -1
  32. package/dist/core/response.js +32 -0
  33. package/dist/core/response.js.map +1 -1
  34. package/dist/core/session.d.ts +23 -0
  35. package/dist/core/session.d.ts.map +1 -1
  36. package/dist/core/session.js +108 -4
  37. package/dist/core/session.js.map +1 -1
  38. package/dist/core/validation.d.ts +11 -0
  39. package/dist/core/validation.d.ts.map +1 -1
  40. package/dist/core/validation.js +22 -1
  41. package/dist/core/validation.js.map +1 -1
  42. package/dist/dns/codec.d.ts +37 -0
  43. package/dist/dns/codec.d.ts.map +1 -0
  44. package/dist/dns/codec.js +254 -0
  45. package/dist/dns/codec.js.map +1 -0
  46. package/dist/dns/doh-resolver.d.ts +52 -0
  47. package/dist/dns/doh-resolver.d.ts.map +1 -0
  48. package/dist/dns/doh-resolver.js +192 -0
  49. package/dist/dns/doh-resolver.js.map +1 -0
  50. package/dist/dns/https-rr.d.ts +51 -0
  51. package/dist/dns/https-rr.d.ts.map +1 -0
  52. package/dist/dns/https-rr.js +127 -0
  53. package/dist/dns/https-rr.js.map +1 -0
  54. package/dist/dns/types.d.ts +110 -0
  55. package/dist/dns/types.d.ts.map +1 -0
  56. package/dist/dns/types.js +34 -0
  57. package/dist/dns/types.js.map +1 -0
  58. package/dist/hsts/store.d.ts +41 -0
  59. package/dist/hsts/store.d.ts.map +1 -0
  60. package/dist/hsts/store.js +171 -0
  61. package/dist/hsts/store.js.map +1 -0
  62. package/dist/hsts/types.d.ts +28 -0
  63. package/dist/hsts/types.d.ts.map +1 -0
  64. package/dist/hsts/types.js +2 -0
  65. package/dist/hsts/types.js.map +1 -0
  66. package/dist/http/alt-svc.d.ts +85 -0
  67. package/dist/http/alt-svc.d.ts.map +1 -0
  68. package/dist/http/alt-svc.js +220 -0
  69. package/dist/http/alt-svc.js.map +1 -0
  70. package/dist/http/form-data.d.ts +59 -0
  71. package/dist/http/form-data.d.ts.map +1 -0
  72. package/dist/http/form-data.js +90 -0
  73. package/dist/http/form-data.js.map +1 -0
  74. package/dist/http/h1/client.d.ts.map +1 -1
  75. package/dist/http/h1/client.js +21 -3
  76. package/dist/http/h1/client.js.map +1 -1
  77. package/dist/http/h1/encoder.d.ts +17 -0
  78. package/dist/http/h1/encoder.d.ts.map +1 -1
  79. package/dist/http/h1/encoder.js +53 -5
  80. package/dist/http/h1/encoder.js.map +1 -1
  81. package/dist/http/h1/parser.d.ts.map +1 -1
  82. package/dist/http/h1/parser.js +7 -1
  83. package/dist/http/h1/parser.js.map +1 -1
  84. package/dist/http/h2/client.d.ts.map +1 -1
  85. package/dist/http/h2/client.js +58 -8
  86. package/dist/http/h2/client.js.map +1 -1
  87. package/dist/http/h2/hpack.d.ts +7 -0
  88. package/dist/http/h2/hpack.d.ts.map +1 -1
  89. package/dist/http/h2/hpack.js +13 -0
  90. package/dist/http/h2/hpack.js.map +1 -1
  91. package/dist/http/h3/detection.d.ts +17 -0
  92. package/dist/http/h3/detection.d.ts.map +1 -0
  93. package/dist/http/h3/detection.js +59 -0
  94. package/dist/http/h3/detection.js.map +1 -0
  95. package/dist/http/negotiator.d.ts +26 -1
  96. package/dist/http/negotiator.d.ts.map +1 -1
  97. package/dist/http/negotiator.js +93 -18
  98. package/dist/http/negotiator.js.map +1 -1
  99. package/dist/http/pool.d.ts +2 -2
  100. package/dist/http/pool.d.ts.map +1 -1
  101. package/dist/http/pool.js.map +1 -1
  102. package/dist/index.d.ts +19 -1
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +14 -0
  105. package/dist/index.js.map +1 -1
  106. package/dist/middleware/rate-limiter.d.ts.map +1 -1
  107. package/dist/middleware/rate-limiter.js +4 -0
  108. package/dist/middleware/rate-limiter.js.map +1 -1
  109. package/dist/middleware/retry.js +2 -2
  110. package/dist/middleware/retry.js.map +1 -1
  111. package/dist/proxy/env-proxy.d.ts +21 -0
  112. package/dist/proxy/env-proxy.d.ts.map +1 -0
  113. package/dist/proxy/env-proxy.js +74 -0
  114. package/dist/proxy/env-proxy.js.map +1 -0
  115. package/dist/proxy/http-proxy.d.ts +2 -0
  116. package/dist/proxy/http-proxy.d.ts.map +1 -1
  117. package/dist/proxy/http-proxy.js +29 -6
  118. package/dist/proxy/http-proxy.js.map +1 -1
  119. package/dist/proxy/socks.js +10 -1
  120. package/dist/proxy/socks.js.map +1 -1
  121. package/dist/sse/parser.d.ts +70 -0
  122. package/dist/sse/parser.d.ts.map +1 -0
  123. package/dist/sse/parser.js +153 -0
  124. package/dist/sse/parser.js.map +1 -0
  125. package/dist/tls/ech.d.ts +147 -0
  126. package/dist/tls/ech.d.ts.map +1 -0
  127. package/dist/tls/ech.js +401 -0
  128. package/dist/tls/ech.js.map +1 -0
  129. package/dist/tls/node-engine.d.ts +9 -1
  130. package/dist/tls/node-engine.d.ts.map +1 -1
  131. package/dist/tls/node-engine.js +54 -1
  132. package/dist/tls/node-engine.js.map +1 -1
  133. package/dist/tls/pin-verification.d.ts +9 -0
  134. package/dist/tls/pin-verification.d.ts.map +1 -0
  135. package/dist/tls/pin-verification.js +34 -0
  136. package/dist/tls/pin-verification.js.map +1 -0
  137. package/dist/tls/session-cache.d.ts +70 -0
  138. package/dist/tls/session-cache.d.ts.map +1 -0
  139. package/dist/tls/session-cache.js +80 -0
  140. package/dist/tls/session-cache.js.map +1 -0
  141. package/dist/tls/stealth/client-hello.d.ts +21 -0
  142. package/dist/tls/stealth/client-hello.d.ts.map +1 -1
  143. package/dist/tls/stealth/client-hello.js +116 -0
  144. package/dist/tls/stealth/client-hello.js.map +1 -1
  145. package/dist/tls/stealth/engine.d.ts.map +1 -1
  146. package/dist/tls/stealth/engine.js +152 -30
  147. package/dist/tls/stealth/engine.js.map +1 -1
  148. package/dist/tls/stealth/handshake.d.ts +2 -1
  149. package/dist/tls/stealth/handshake.d.ts.map +1 -1
  150. package/dist/tls/stealth/handshake.js +118 -5
  151. package/dist/tls/stealth/handshake.js.map +1 -1
  152. package/dist/tls/stealth/tls12-handshake.d.ts +14 -0
  153. package/dist/tls/stealth/tls12-handshake.d.ts.map +1 -0
  154. package/dist/tls/stealth/tls12-handshake.js +462 -0
  155. package/dist/tls/stealth/tls12-handshake.js.map +1 -0
  156. package/dist/tls/types.d.ts +40 -0
  157. package/dist/tls/types.d.ts.map +1 -1
  158. package/dist/utils/encoding.d.ts +8 -6
  159. package/dist/utils/encoding.d.ts.map +1 -1
  160. package/dist/utils/encoding.js +92 -24
  161. package/dist/utils/encoding.js.map +1 -1
  162. package/dist/utils/happy-eyeballs.d.ts +3 -0
  163. package/dist/utils/happy-eyeballs.d.ts.map +1 -1
  164. package/dist/utils/happy-eyeballs.js +42 -2
  165. package/dist/utils/happy-eyeballs.js.map +1 -1
  166. package/dist/ws/client.d.ts +3 -0
  167. package/dist/ws/client.d.ts.map +1 -1
  168. package/dist/ws/client.js +63 -7
  169. package/dist/ws/client.js.map +1 -1
  170. package/dist/ws/frame.d.ts +4 -2
  171. package/dist/ws/frame.d.ts.map +1 -1
  172. package/dist/ws/frame.js +18 -18
  173. package/dist/ws/frame.js.map +1 -1
  174. package/dist/ws/permessage-deflate.d.ts +58 -0
  175. package/dist/ws/permessage-deflate.d.ts.map +1 -0
  176. package/dist/ws/permessage-deflate.js +148 -0
  177. package/dist/ws/permessage-deflate.js.map +1 -0
  178. package/package.json +3 -2
@@ -0,0 +1,127 @@
1
+ /**
2
+ * HTTPS Resource Record resolver (RFC 9460).
3
+ *
4
+ * Queries HTTPS/SVCB DNS records to discover:
5
+ * - ECH (Encrypted Client Hello) configuration keys
6
+ * - ALPN protocol hints (e.g. h2, h3)
7
+ * - IP address hints for faster connection setup
8
+ * - Port overrides
9
+ *
10
+ * Can use either the system DNS resolver (via `node:dns`) or a DoH
11
+ * resolver for encrypted queries.
12
+ *
13
+ * @see https://datatracker.ietf.org/doc/html/rfc9460
14
+ */
15
+ import { Resolver } from "node:dns/promises";
16
+ import { DoHResolver } from "./doh-resolver.js";
17
+ import { parseSVCBRecord } from "./codec.js";
18
+ import { RTYPE } from "./types.js";
19
+ /**
20
+ * Resolver for HTTPS/SVCB DNS Resource Records (RFC 9460).
21
+ *
22
+ * Supports two modes:
23
+ * 1. **System DNS** — Uses `node:dns` (resolveAny or raw query).
24
+ * 2. **DoH** — Uses a DoHResolver for encrypted HTTPS-RR queries.
25
+ */
26
+ export class HTTPSRRResolver {
27
+ dohResolver;
28
+ systemResolver;
29
+ constructor(dohConfig) {
30
+ if (dohConfig) {
31
+ this.dohResolver = new DoHResolver(dohConfig);
32
+ }
33
+ this.systemResolver = new Resolver();
34
+ }
35
+ /**
36
+ * Queries HTTPS records for a hostname and parses the results.
37
+ *
38
+ * @param hostname The domain to look up HTTPS records for.
39
+ * @param signal Optional AbortSignal for cancellation.
40
+ * @returns Parsed HTTPS-RR result with SVCB params, or null if no records found.
41
+ */
42
+ async resolve(hostname, signal) {
43
+ try {
44
+ let svcbRecords;
45
+ if (this.dohResolver) {
46
+ svcbRecords = await this.resolveViaDoH(hostname, signal);
47
+ }
48
+ else {
49
+ svcbRecords = await this.resolveViaSystem(hostname);
50
+ }
51
+ if (svcbRecords.length === 0)
52
+ return null;
53
+ svcbRecords.sort((a, b) => a.priority - b.priority);
54
+ const serviceRecords = svcbRecords.filter((r) => r.priority > 0);
55
+ if (serviceRecords.length === 0)
56
+ return null;
57
+ const best = serviceRecords[0];
58
+ const addresses = [];
59
+ for (const rec of serviceRecords) {
60
+ if (rec.ipv4Hints) {
61
+ for (const addr of rec.ipv4Hints) {
62
+ addresses.push({ address: addr, family: 4 });
63
+ }
64
+ }
65
+ if (rec.ipv6Hints) {
66
+ for (const addr of rec.ipv6Hints) {
67
+ addresses.push({ address: addr, family: 6 });
68
+ }
69
+ }
70
+ }
71
+ const echRecord = serviceRecords.find((r) => r.echConfigList);
72
+ return {
73
+ svcb: svcbRecords,
74
+ echConfigList: echRecord?.echConfigList,
75
+ alpn: best.alpn,
76
+ addresses,
77
+ port: best.port,
78
+ };
79
+ }
80
+ catch {
81
+ return null;
82
+ }
83
+ }
84
+ /**
85
+ * Resolves HTTPS records via DoH.
86
+ */
87
+ async resolveViaDoH(hostname, signal) {
88
+ const records = await this.dohResolver.query(hostname, "HTTPS", signal);
89
+ return records.filter((r) => r.type === RTYPE.HTTPS || r.type === RTYPE.SVCB).map((r) => parseSVCBRecord(r.data));
90
+ }
91
+ /**
92
+ * Resolves HTTPS records via the system DNS resolver.
93
+ * Uses raw DNS query + decode since node:dns doesn't natively support type 65.
94
+ */
95
+ async resolveViaSystem(hostname) {
96
+ try {
97
+ const results = await this.systemResolver.resolve(hostname, "HTTPS").catch(() => []);
98
+ if (Array.isArray(results) && results.length > 0) {
99
+ return results.map((r) => this.parseNativeHTTPSRecord(r));
100
+ }
101
+ }
102
+ catch { }
103
+ return [];
104
+ }
105
+ /**
106
+ * Parses a native Node.js HTTPS DNS record into our SVCBRecord format.
107
+ * Node.js 22+ may return HTTPS records with a specific structure.
108
+ */
109
+ parseNativeHTTPSRecord(record) {
110
+ const result = {
111
+ priority: record.priority ?? 0,
112
+ target: record.target ?? "",
113
+ };
114
+ if (record.alpn)
115
+ result.alpn = Array.isArray(record.alpn) ? record.alpn : [record.alpn];
116
+ if (record.port)
117
+ result.port = record.port;
118
+ if (record.ipv4hint)
119
+ result.ipv4Hints = Array.isArray(record.ipv4hint) ? record.ipv4hint : [record.ipv4hint];
120
+ if (record.ipv6hint)
121
+ result.ipv6Hints = Array.isArray(record.ipv6hint) ? record.ipv6hint : [record.ipv6hint];
122
+ if (record.ech)
123
+ result.echConfigList = Buffer.isBuffer(record.ech) ? record.ech : Buffer.from(record.ech, "base64");
124
+ return result;
125
+ }
126
+ }
127
+ //# sourceMappingURL=https-rr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"https-rr.js","sourceRoot":"","sources":["../../src/dns/https-rr.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Type definitions for the DNS resolution subsystem, including DNS-over-HTTPS
3
+ * (RFC 8484), HTTPS/SVCB resource records (RFC 9460), and resolver interfaces.
4
+ */
5
+ /**
6
+ * A resolved IP address entry.
7
+ */
8
+ export interface ResolvedAddress {
9
+ address: string;
10
+ family: 4 | 6;
11
+ }
12
+ /**
13
+ * DNS query types used by the resolver.
14
+ */
15
+ export type DNSRecordType = "A" | "AAAA" | "HTTPS" | "SVCB";
16
+ /**
17
+ * A parsed DNS resource record.
18
+ */
19
+ export interface DNSRecord {
20
+ name: string;
21
+ type: number;
22
+ ttl: number;
23
+ data: Buffer;
24
+ }
25
+ /**
26
+ * Wire-format DNS record type numbers.
27
+ */
28
+ export declare const RTYPE: {
29
+ readonly A: 1;
30
+ readonly AAAA: 28;
31
+ readonly HTTPS: 65;
32
+ readonly SVCB: 64;
33
+ };
34
+ /**
35
+ * Wire-format DNS class numbers.
36
+ */
37
+ export declare const RCLASS: {
38
+ readonly IN: 1;
39
+ };
40
+ /**
41
+ * SvcParam keys defined in RFC 9460 §14.3.
42
+ */
43
+ export declare const SvcParamKey: {
44
+ readonly MANDATORY: 0;
45
+ readonly ALPN: 1;
46
+ readonly NO_DEFAULT_ALPN: 2;
47
+ readonly PORT: 3;
48
+ readonly IPV4HINT: 4;
49
+ readonly ECH: 5;
50
+ readonly IPV6HINT: 6;
51
+ /** draft-ietf-dnsop-svcb-https §14 — DNS-over-HTTPS path template */
52
+ readonly DOHPATH: 7;
53
+ };
54
+ /**
55
+ * Parsed HTTPS/SVCB record service parameters (RFC 9460).
56
+ */
57
+ export interface SVCBRecord {
58
+ /** SvcPriority — 0 = AliasMode, >0 = ServiceMode. */
59
+ priority: number;
60
+ /** TargetName — the target domain (empty = use record owner). */
61
+ target: string;
62
+ /** ALPN protocol identifiers (e.g. ["h2", "h3"]). */
63
+ alpn?: string[];
64
+ /** TCP port override. */
65
+ port?: number;
66
+ /** IPv4 address hints. */
67
+ ipv4Hints?: string[];
68
+ /** IPv6 address hints. */
69
+ ipv6Hints?: string[];
70
+ /** ECH configuration (raw bytes). */
71
+ echConfigList?: Buffer;
72
+ /** Whether no-default-alpn is set. */
73
+ noDefaultAlpn?: boolean;
74
+ }
75
+ /**
76
+ * Configuration options for the DoH resolver.
77
+ */
78
+ export interface DoHConfig {
79
+ /** DoH server URL (e.g. "https://1.1.1.1/dns-query"). */
80
+ server: string;
81
+ /**
82
+ * HTTP method for DoH queries.
83
+ * - `"GET"`: DNS wire-format base64url-encoded in `?dns=` query parameter.
84
+ * - `"POST"`: DNS wire-format in request body.
85
+ * @default "POST"
86
+ */
87
+ method?: "GET" | "POST";
88
+ /** Timeout in ms for each DoH query. @default 5000 */
89
+ timeout?: number;
90
+ /**
91
+ * Whether to bootstrap the DoH server address via system DNS if the
92
+ * server URL uses a hostname instead of an IP.
93
+ * @default true
94
+ */
95
+ bootstrap?: boolean;
96
+ }
97
+ /**
98
+ * Combined DNS configuration for the library.
99
+ */
100
+ export interface DNSConfig {
101
+ /** DoH resolver configuration. When set, DNS queries use DNS-over-HTTPS. */
102
+ doh?: DoHConfig;
103
+ /**
104
+ * Whether to query HTTPS/SVCB records alongside A/AAAA.
105
+ * Enables ECH key discovery, ALPN hints, and IP hints.
106
+ * @default false
107
+ */
108
+ httpsRR?: boolean;
109
+ }
110
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/dns/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;CACf;AAED;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,GAAG,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,eAAO,MAAM,KAAK;;;;;CAKR,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,MAAM;;CAET,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;IAQtB,qEAAqE;;CAE7D,CAAC;AAEX;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,yBAAyB;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,qCAAqC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sCAAsC;IACtC,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,yDAAyD;IACzD,MAAM,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,4EAA4E;IAC5E,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Type definitions for the DNS resolution subsystem, including DNS-over-HTTPS
3
+ * (RFC 8484), HTTPS/SVCB resource records (RFC 9460), and resolver interfaces.
4
+ */
5
+ /**
6
+ * Wire-format DNS record type numbers.
7
+ */
8
+ export const RTYPE = {
9
+ A: 1,
10
+ AAAA: 28,
11
+ HTTPS: 65,
12
+ SVCB: 64,
13
+ };
14
+ /**
15
+ * Wire-format DNS class numbers.
16
+ */
17
+ export const RCLASS = {
18
+ IN: 1,
19
+ };
20
+ /**
21
+ * SvcParam keys defined in RFC 9460 §14.3.
22
+ */
23
+ export const SvcParamKey = {
24
+ MANDATORY: 0,
25
+ ALPN: 1,
26
+ NO_DEFAULT_ALPN: 2,
27
+ PORT: 3,
28
+ IPV4HINT: 4,
29
+ ECH: 5,
30
+ IPV6HINT: 6,
31
+ /** draft-ietf-dnsop-svcb-https §14 — DNS-over-HTTPS path template */
32
+ DOHPATH: 7,
33
+ };
34
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/dns/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAyBH;;GAEG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,CAAC,EAAE,CAAC;IACJ,IAAI,EAAE,EAAE;IACR,KAAK,EAAE,EAAE;IACT,IAAI,EAAE,EAAE;CACA,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,EAAE,EAAE,CAAC;CACG,CAAC;AAEX;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,SAAS,EAAE,CAAC;IACZ,IAAI,EAAE,CAAC;IACP,eAAe,EAAE,CAAC;IAClB,IAAI,EAAE,CAAC;IACP,QAAQ,EAAE,CAAC;IACX,GAAG,EAAE,CAAC;IACN,QAAQ,EAAE,CAAC;IACX,qEAAqE;IACrE,OAAO,EAAE,CAAC;CACF,CAAC"}
@@ -0,0 +1,41 @@
1
+ import type { HSTSConfig } from "./types.js";
2
+ /**
3
+ * In-memory HSTS policy store implementing RFC 6797.
4
+ *
5
+ * Parses `Strict-Transport-Security` response headers, stores per-host policies,
6
+ * and upgrades `http://` URLs to `https://` when an active policy matches.
7
+ */
8
+ export declare class HSTSStore {
9
+ private readonly policies;
10
+ constructor(config?: HSTSConfig);
11
+ /**
12
+ * Seeds a preload entry with a very long max-age (20 years).
13
+ */
14
+ private addPreload;
15
+ /**
16
+ * Parses a `Strict-Transport-Security` header value and stores the policy.
17
+ * Only processes headers received over a secure (HTTPS) connection, as
18
+ * required by RFC 6797 §8.1.
19
+ *
20
+ * @param host - The hostname from the request URL.
21
+ * @param value - The raw STS header value (e.g. `"max-age=31536000; includeSubDomains"`).
22
+ * @param isSecure - Whether the response was received over HTTPS.
23
+ */
24
+ parseHeader(host: string, value: string, isSecure: boolean): void;
25
+ /**
26
+ * Checks whether the given host has an active HSTS policy, either via
27
+ * congruent match or superdomain match with `includeSubDomains`.
28
+ */
29
+ isSecure(host: string): boolean;
30
+ /**
31
+ * If there is an active HSTS policy for the host in the given URL,
32
+ * upgrades the scheme from `http:` to `https:`. Returns the original
33
+ * URL string if no upgrade is needed.
34
+ */
35
+ upgradeURL(urlString: string): string;
36
+ /** Returns the number of active policies stored. */
37
+ get size(): number;
38
+ /** Clears all stored policies. */
39
+ clear(): void;
40
+ }
41
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/hsts/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAA+B,MAAM,YAAY,CAAC;AAE1E;;;;;GAKG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgC;gBAE7C,MAAM,CAAC,EAAE,UAAU;IAQ/B;;OAEG;IACH,OAAO,CAAC,UAAU;IAUlB;;;;;;;;OAQG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI;IA2BjE;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAwB/B;;;;OAIG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAkBrC,oDAAoD;IACpD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,kCAAkC;IAClC,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * In-memory HSTS policy store implementing RFC 6797.
3
+ *
4
+ * Parses `Strict-Transport-Security` response headers, stores per-host policies,
5
+ * and upgrades `http://` URLs to `https://` when an active policy matches.
6
+ */
7
+ export class HSTSStore {
8
+ policies = new Map();
9
+ constructor(config) {
10
+ if (config?.preload) {
11
+ for (const entry of config.preload) {
12
+ this.addPreload(entry);
13
+ }
14
+ }
15
+ }
16
+ /**
17
+ * Seeds a preload entry with a very long max-age (20 years).
18
+ */
19
+ addPreload(entry) {
20
+ const host = canonicalizeHost(entry.host);
21
+ if (!host)
22
+ return;
23
+ this.policies.set(host, {
24
+ host,
25
+ expires: Date.now() + 20 * 365 * 24 * 60 * 60 * 1000,
26
+ includeSubDomains: entry.includeSubDomains ?? false,
27
+ });
28
+ }
29
+ /**
30
+ * Parses a `Strict-Transport-Security` header value and stores the policy.
31
+ * Only processes headers received over a secure (HTTPS) connection, as
32
+ * required by RFC 6797 §8.1.
33
+ *
34
+ * @param host - The hostname from the request URL.
35
+ * @param value - The raw STS header value (e.g. `"max-age=31536000; includeSubDomains"`).
36
+ * @param isSecure - Whether the response was received over HTTPS.
37
+ */
38
+ parseHeader(host, value, isSecure) {
39
+ if (!isSecure)
40
+ return;
41
+ const canonical = canonicalizeHost(host);
42
+ if (!canonical)
43
+ return;
44
+ if (isIPAddress(canonical))
45
+ return;
46
+ const directives = parseDirectives(value);
47
+ const maxAgeStr = directives.get("max-age");
48
+ if (maxAgeStr === undefined)
49
+ return;
50
+ const maxAge = parseInt(maxAgeStr, 10);
51
+ if (!Number.isFinite(maxAge) || maxAge < 0)
52
+ return;
53
+ if (maxAge === 0) {
54
+ this.policies.delete(canonical);
55
+ return;
56
+ }
57
+ this.policies.set(canonical, {
58
+ host: canonical,
59
+ expires: Date.now() + maxAge * 1000,
60
+ includeSubDomains: directives.has("includesubdomains"),
61
+ });
62
+ }
63
+ /**
64
+ * Checks whether the given host has an active HSTS policy, either via
65
+ * congruent match or superdomain match with `includeSubDomains`.
66
+ */
67
+ isSecure(host) {
68
+ const canonical = canonicalizeHost(host);
69
+ if (!canonical)
70
+ return false;
71
+ if (isIPAddress(canonical))
72
+ return false;
73
+ const exact = this.policies.get(canonical);
74
+ if (exact) {
75
+ if (Date.now() < exact.expires)
76
+ return true;
77
+ this.policies.delete(canonical);
78
+ }
79
+ const parts = canonical.split(".");
80
+ for (let i = 1; i < parts.length; i++) {
81
+ const parent = parts.slice(i).join(".");
82
+ const entry = this.policies.get(parent);
83
+ if (entry && entry.includeSubDomains) {
84
+ if (Date.now() < entry.expires)
85
+ return true;
86
+ this.policies.delete(parent);
87
+ }
88
+ }
89
+ return false;
90
+ }
91
+ /**
92
+ * If there is an active HSTS policy for the host in the given URL,
93
+ * upgrades the scheme from `http:` to `https:`. Returns the original
94
+ * URL string if no upgrade is needed.
95
+ */
96
+ upgradeURL(urlString) {
97
+ let parsed;
98
+ try {
99
+ parsed = new URL(urlString);
100
+ }
101
+ catch {
102
+ return urlString;
103
+ }
104
+ if (parsed.protocol !== "http:")
105
+ return urlString;
106
+ if (this.isSecure(parsed.hostname)) {
107
+ parsed.protocol = "https:";
108
+ return parsed.toString();
109
+ }
110
+ return urlString;
111
+ }
112
+ /** Returns the number of active policies stored. */
113
+ get size() {
114
+ return this.policies.size;
115
+ }
116
+ /** Clears all stored policies. */
117
+ clear() {
118
+ this.policies.clear();
119
+ }
120
+ }
121
+ /** Lowercases the host and strips a trailing dot. */
122
+ function canonicalizeHost(host) {
123
+ let h = host.toLowerCase().trim();
124
+ if (h.endsWith("."))
125
+ h = h.slice(0, -1);
126
+ return h;
127
+ }
128
+ /** Returns `true` if the string looks like an IPv4 or IPv6 address. */
129
+ function isIPAddress(host) {
130
+ if (host.startsWith("["))
131
+ return true;
132
+ const parts = host.split(".");
133
+ if (parts.length === 4 &&
134
+ parts.every((p) => {
135
+ if (!/^\d{1,3}$/.test(p))
136
+ return false;
137
+ const n = parseInt(p, 10);
138
+ return n >= 0 && n <= 255;
139
+ }))
140
+ return true;
141
+ if (host.includes(":"))
142
+ return true;
143
+ return false;
144
+ }
145
+ /**
146
+ * Parses the STS header value into a case-insensitive directive map.
147
+ * Directive names are lowercased; quoted string values are unquoted.
148
+ */
149
+ function parseDirectives(value) {
150
+ const directives = new Map();
151
+ const parts = value.split(";");
152
+ for (const part of parts) {
153
+ const trimmed = part.trim();
154
+ if (!trimmed)
155
+ continue;
156
+ const eqIdx = trimmed.indexOf("=");
157
+ if (eqIdx === -1) {
158
+ directives.set(trimmed.toLowerCase(), "");
159
+ }
160
+ else {
161
+ const name = trimmed.slice(0, eqIdx).trim().toLowerCase();
162
+ let val = trimmed.slice(eqIdx + 1).trim();
163
+ if (val.startsWith('"') && val.endsWith('"')) {
164
+ val = val.slice(1, -1);
165
+ }
166
+ directives.set(name, val);
167
+ }
168
+ }
169
+ return directives;
170
+ }
171
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/hsts/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Configuration for HTTP Strict Transport Security (RFC 6797).
3
+ */
4
+ export interface HSTSConfig {
5
+ /** Enable HSTS policy enforcement. Defaults to `true` when an HSTSStore is provided. */
6
+ enabled?: boolean;
7
+ /** Optional preload entries to seed the store with known HSTS hosts. */
8
+ preload?: HSTSPreloadEntry[];
9
+ }
10
+ /**
11
+ * A preload entry for seeding the HSTS store with known-secure hosts.
12
+ */
13
+ export interface HSTSPreloadEntry {
14
+ host: string;
15
+ includeSubDomains?: boolean;
16
+ }
17
+ /**
18
+ * Internal representation of a stored HSTS policy for a single host.
19
+ */
20
+ export interface HSTSEntry {
21
+ /** The canonicalized hostname (lowercase, no trailing dot). */
22
+ host: string;
23
+ /** Absolute timestamp (ms since epoch) when this policy expires. */
24
+ expires: number;
25
+ /** Whether the policy applies to all subdomains of the host. */
26
+ includeSubDomains: boolean;
27
+ }
28
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/hsts/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,wFAAwF;IACxF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,wEAAwE;IACxE,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,iBAAiB,EAAE,OAAO,CAAC;CAC5B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/hsts/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Alt-Svc (Alternative Services) implementation per RFC 7838.
3
+ *
4
+ * Parses `Alt-Svc` response headers and maintains a store of alternative
5
+ * service entries. This is the primary mechanism for HTTP/3 discovery:
6
+ * servers advertise `h3=":443"` in Alt-Svc to indicate QUIC availability.
7
+ *
8
+ * @see https://datatracker.ietf.org/doc/html/rfc7838
9
+ */
10
+ /**
11
+ * A single alternative service entry parsed from an Alt-Svc header.
12
+ */
13
+ export interface AltSvcEntry {
14
+ /** ALPN protocol identifier (e.g. "h3", "h3-29", "h2"). */
15
+ alpn: string;
16
+ /** Authority — host:port of the alternative service. */
17
+ host: string;
18
+ port: number;
19
+ /** Maximum age in seconds before this entry expires. */
20
+ maxAge: number;
21
+ /** Whether the entry has been confirmed via a successful connection. */
22
+ persist: boolean;
23
+ /** Timestamp (ms) when this entry was stored. */
24
+ storedAt: number;
25
+ }
26
+ /**
27
+ * Configuration for the Alt-Svc store.
28
+ */
29
+ export interface AltSvcConfig {
30
+ /** Maximum number of entries across all origins. @default 1000 */
31
+ maxEntries?: number;
32
+ /** Whether to enable Alt-Svc processing. @default true */
33
+ enabled?: boolean;
34
+ }
35
+ /**
36
+ * In-memory store for Alt-Svc (Alternative Services) per RFC 7838.
37
+ *
38
+ * Tracks alternative service advertisements from HTTP response headers
39
+ * and provides lookup for the best alternative to use for a given origin.
40
+ *
41
+ * Primary use case: HTTP/3 discovery via `h3=":443"` advertisements.
42
+ */
43
+ export declare class AltSvcStore {
44
+ private readonly entries;
45
+ private readonly maxEntries;
46
+ private totalEntries;
47
+ constructor(config?: AltSvcConfig);
48
+ /**
49
+ * Parses an `Alt-Svc` response header value and stores the entries
50
+ * associated with the given origin.
51
+ *
52
+ * @param origin Origin of the response (e.g. "https://example.com:443").
53
+ * @param headerValue Raw `Alt-Svc` header value.
54
+ *
55
+ * @example
56
+ * store.parseHeader("https://example.com:443", 'h3=":443"; ma=86400, h2=":443"');
57
+ */
58
+ parseHeader(origin: string, headerValue: string): void;
59
+ /**
60
+ * Looks up the best available alternative service for a given origin.
61
+ * Prefers h3 over h2. Expired entries are pruned during lookup.
62
+ *
63
+ * @param origin Origin to look up alternatives for.
64
+ * @returns The best Alt-Svc entry, or undefined if no valid alternative exists.
65
+ */
66
+ lookup(origin: string): AltSvcEntry | undefined;
67
+ /**
68
+ * Checks if there's an h3 alternative available for an origin.
69
+ */
70
+ hasH3(origin: string): boolean;
71
+ /**
72
+ * Removes all alternative service entries for a specific origin.
73
+ */
74
+ clear(origin: string): void;
75
+ /**
76
+ * Removes all entries from the store.
77
+ */
78
+ clearAll(): void;
79
+ /**
80
+ * Returns the total number of stored entries.
81
+ */
82
+ get size(): number;
83
+ private evictOldest;
84
+ }
85
+ //# sourceMappingURL=alt-svc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alt-svc.d.ts","sourceRoot":"","sources":["../../src/http/alt-svc.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;IACjB,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAKD;;;;;;;GAOG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoC;IAC5D,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,YAAY,CAAK;gBAEb,MAAM,CAAC,EAAE,YAAY;IAIjC;;;;;;;;;OASG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI;IAyBtD;;;;;;OAMG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IA2B/C;;OAEG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAK9B;;OAEG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAQ3B;;OAEG;IACH,QAAQ,IAAI,IAAI;IAKhB;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,OAAO,CAAC,WAAW;CAiBpB"}