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.
- package/README.md +41 -8
- package/dist/cache/store.d.ts +89 -0
- package/dist/cache/store.d.ts.map +1 -0
- package/dist/cache/store.js +402 -0
- package/dist/cache/store.js.map +1 -0
- package/dist/cache/types.d.ts +101 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/cache/types.js +2 -0
- package/dist/cache/types.js.map +1 -0
- package/dist/cookies/jar.d.ts +20 -0
- package/dist/cookies/jar.d.ts.map +1 -1
- package/dist/cookies/jar.js +64 -10
- package/dist/cookies/jar.js.map +1 -1
- package/dist/cookies/parser.d.ts +2 -10
- package/dist/cookies/parser.d.ts.map +1 -1
- package/dist/cookies/parser.js +49 -2
- package/dist/cookies/parser.js.map +1 -1
- package/dist/cookies/psl-data.d.ts +12 -0
- package/dist/cookies/psl-data.d.ts.map +1 -0
- package/dist/cookies/psl-data.js +10166 -0
- package/dist/cookies/psl-data.js.map +1 -0
- package/dist/cookies/public-suffix.d.ts +37 -0
- package/dist/cookies/public-suffix.d.ts.map +1 -0
- package/dist/cookies/public-suffix.js +140 -0
- package/dist/cookies/public-suffix.js.map +1 -0
- package/dist/core/client.js +4 -0
- package/dist/core/client.js.map +1 -1
- package/dist/core/request.d.ts +73 -3
- package/dist/core/request.d.ts.map +1 -1
- package/dist/core/response.d.ts +22 -0
- package/dist/core/response.d.ts.map +1 -1
- package/dist/core/response.js +32 -0
- package/dist/core/response.js.map +1 -1
- package/dist/core/session.d.ts +23 -0
- package/dist/core/session.d.ts.map +1 -1
- package/dist/core/session.js +108 -4
- package/dist/core/session.js.map +1 -1
- package/dist/core/validation.d.ts +11 -0
- package/dist/core/validation.d.ts.map +1 -1
- package/dist/core/validation.js +22 -1
- package/dist/core/validation.js.map +1 -1
- package/dist/dns/codec.d.ts +37 -0
- package/dist/dns/codec.d.ts.map +1 -0
- package/dist/dns/codec.js +254 -0
- package/dist/dns/codec.js.map +1 -0
- package/dist/dns/doh-resolver.d.ts +52 -0
- package/dist/dns/doh-resolver.d.ts.map +1 -0
- package/dist/dns/doh-resolver.js +192 -0
- package/dist/dns/doh-resolver.js.map +1 -0
- package/dist/dns/https-rr.d.ts +51 -0
- package/dist/dns/https-rr.d.ts.map +1 -0
- package/dist/dns/https-rr.js +127 -0
- package/dist/dns/https-rr.js.map +1 -0
- package/dist/dns/types.d.ts +110 -0
- package/dist/dns/types.d.ts.map +1 -0
- package/dist/dns/types.js +34 -0
- package/dist/dns/types.js.map +1 -0
- package/dist/hsts/store.d.ts +41 -0
- package/dist/hsts/store.d.ts.map +1 -0
- package/dist/hsts/store.js +171 -0
- package/dist/hsts/store.js.map +1 -0
- package/dist/hsts/types.d.ts +28 -0
- package/dist/hsts/types.d.ts.map +1 -0
- package/dist/hsts/types.js +2 -0
- package/dist/hsts/types.js.map +1 -0
- package/dist/http/alt-svc.d.ts +85 -0
- package/dist/http/alt-svc.d.ts.map +1 -0
- package/dist/http/alt-svc.js +220 -0
- package/dist/http/alt-svc.js.map +1 -0
- package/dist/http/form-data.d.ts +59 -0
- package/dist/http/form-data.d.ts.map +1 -0
- package/dist/http/form-data.js +90 -0
- package/dist/http/form-data.js.map +1 -0
- package/dist/http/h1/client.d.ts.map +1 -1
- package/dist/http/h1/client.js +21 -3
- package/dist/http/h1/client.js.map +1 -1
- package/dist/http/h1/encoder.d.ts +17 -0
- package/dist/http/h1/encoder.d.ts.map +1 -1
- package/dist/http/h1/encoder.js +53 -5
- package/dist/http/h1/encoder.js.map +1 -1
- package/dist/http/h1/parser.d.ts.map +1 -1
- package/dist/http/h1/parser.js +7 -1
- package/dist/http/h1/parser.js.map +1 -1
- package/dist/http/h2/client.d.ts.map +1 -1
- package/dist/http/h2/client.js +58 -8
- package/dist/http/h2/client.js.map +1 -1
- package/dist/http/h2/hpack.d.ts +7 -0
- package/dist/http/h2/hpack.d.ts.map +1 -1
- package/dist/http/h2/hpack.js +13 -0
- package/dist/http/h2/hpack.js.map +1 -1
- package/dist/http/h3/detection.d.ts +17 -0
- package/dist/http/h3/detection.d.ts.map +1 -0
- package/dist/http/h3/detection.js +59 -0
- package/dist/http/h3/detection.js.map +1 -0
- package/dist/http/negotiator.d.ts +26 -1
- package/dist/http/negotiator.d.ts.map +1 -1
- package/dist/http/negotiator.js +93 -18
- package/dist/http/negotiator.js.map +1 -1
- package/dist/http/pool.d.ts +2 -2
- package/dist/http/pool.d.ts.map +1 -1
- package/dist/http/pool.js.map +1 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -1
- package/dist/middleware/rate-limiter.d.ts.map +1 -1
- package/dist/middleware/rate-limiter.js +4 -0
- package/dist/middleware/rate-limiter.js.map +1 -1
- package/dist/middleware/retry.js +2 -2
- package/dist/middleware/retry.js.map +1 -1
- package/dist/proxy/env-proxy.d.ts +21 -0
- package/dist/proxy/env-proxy.d.ts.map +1 -0
- package/dist/proxy/env-proxy.js +74 -0
- package/dist/proxy/env-proxy.js.map +1 -0
- package/dist/proxy/http-proxy.d.ts +2 -0
- package/dist/proxy/http-proxy.d.ts.map +1 -1
- package/dist/proxy/http-proxy.js +29 -6
- package/dist/proxy/http-proxy.js.map +1 -1
- package/dist/proxy/socks.js +10 -1
- package/dist/proxy/socks.js.map +1 -1
- package/dist/sse/parser.d.ts +70 -0
- package/dist/sse/parser.d.ts.map +1 -0
- package/dist/sse/parser.js +153 -0
- package/dist/sse/parser.js.map +1 -0
- package/dist/tls/ech.d.ts +147 -0
- package/dist/tls/ech.d.ts.map +1 -0
- package/dist/tls/ech.js +401 -0
- package/dist/tls/ech.js.map +1 -0
- package/dist/tls/node-engine.d.ts +9 -1
- package/dist/tls/node-engine.d.ts.map +1 -1
- package/dist/tls/node-engine.js +54 -1
- package/dist/tls/node-engine.js.map +1 -1
- package/dist/tls/pin-verification.d.ts +9 -0
- package/dist/tls/pin-verification.d.ts.map +1 -0
- package/dist/tls/pin-verification.js +34 -0
- package/dist/tls/pin-verification.js.map +1 -0
- package/dist/tls/session-cache.d.ts +70 -0
- package/dist/tls/session-cache.d.ts.map +1 -0
- package/dist/tls/session-cache.js +80 -0
- package/dist/tls/session-cache.js.map +1 -0
- package/dist/tls/stealth/client-hello.d.ts +21 -0
- package/dist/tls/stealth/client-hello.d.ts.map +1 -1
- package/dist/tls/stealth/client-hello.js +116 -0
- package/dist/tls/stealth/client-hello.js.map +1 -1
- package/dist/tls/stealth/engine.d.ts.map +1 -1
- package/dist/tls/stealth/engine.js +152 -30
- package/dist/tls/stealth/engine.js.map +1 -1
- package/dist/tls/stealth/handshake.d.ts +2 -1
- package/dist/tls/stealth/handshake.d.ts.map +1 -1
- package/dist/tls/stealth/handshake.js +118 -5
- package/dist/tls/stealth/handshake.js.map +1 -1
- package/dist/tls/stealth/tls12-handshake.d.ts +14 -0
- package/dist/tls/stealth/tls12-handshake.d.ts.map +1 -0
- package/dist/tls/stealth/tls12-handshake.js +462 -0
- package/dist/tls/stealth/tls12-handshake.js.map +1 -0
- package/dist/tls/types.d.ts +40 -0
- package/dist/tls/types.d.ts.map +1 -1
- package/dist/utils/encoding.d.ts +8 -6
- package/dist/utils/encoding.d.ts.map +1 -1
- package/dist/utils/encoding.js +92 -24
- package/dist/utils/encoding.js.map +1 -1
- package/dist/utils/happy-eyeballs.d.ts +3 -0
- package/dist/utils/happy-eyeballs.d.ts.map +1 -1
- package/dist/utils/happy-eyeballs.js +42 -2
- package/dist/utils/happy-eyeballs.js.map +1 -1
- package/dist/ws/client.d.ts +3 -0
- package/dist/ws/client.d.ts.map +1 -1
- package/dist/ws/client.js +63 -7
- package/dist/ws/client.js.map +1 -1
- package/dist/ws/frame.d.ts +4 -2
- package/dist/ws/frame.d.ts.map +1 -1
- package/dist/ws/frame.js +18 -18
- package/dist/ws/frame.js.map +1 -1
- package/dist/ws/permessage-deflate.d.ts +58 -0
- package/dist/ws/permessage-deflate.d.ts.map +1 -0
- package/dist/ws/permessage-deflate.js +148 -0
- package/dist/ws/permessage-deflate.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { NLcURLResponse } from "../core/response.js";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration for the HTTP cache layer (RFC 9111).
|
|
4
|
+
*/
|
|
5
|
+
export interface CacheConfig {
|
|
6
|
+
/** Enable response caching. Defaults to `true` when a CacheStore is provided. */
|
|
7
|
+
enabled?: boolean;
|
|
8
|
+
/** Maximum number of entries to store. Defaults to `1000`. */
|
|
9
|
+
maxEntries?: number;
|
|
10
|
+
/** Maximum total byte size of cached response bodies. Defaults to `50 * 1024 * 1024` (50 MB). */
|
|
11
|
+
maxSize?: number;
|
|
12
|
+
/** Cache mode controlling request/response behavior. */
|
|
13
|
+
mode?: CacheMode;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Cache modes mirroring the Fetch API `cache` option but adapted for
|
|
17
|
+
* a full HTTP client.
|
|
18
|
+
*
|
|
19
|
+
* - `"default"` — Standard caching: serve fresh, revalidate stale.
|
|
20
|
+
* - `"no-store"` — Never read from or write to cache.
|
|
21
|
+
* - `"no-cache"` — Always revalidate with the origin, even if the response is fresh.
|
|
22
|
+
* - `"force-cache"` — Serve from cache regardless of freshness; only fetch on miss.
|
|
23
|
+
* - `"only-if-cached"` — Only return cached responses; fail with 504 on miss.
|
|
24
|
+
*/
|
|
25
|
+
export type CacheMode = "default" | "no-store" | "no-cache" | "force-cache" | "only-if-cached";
|
|
26
|
+
/**
|
|
27
|
+
* Parsed Cache-Control directives from a response header.
|
|
28
|
+
*/
|
|
29
|
+
export interface CacheDirectives {
|
|
30
|
+
maxAge?: number;
|
|
31
|
+
sMaxAge?: number;
|
|
32
|
+
noCache: boolean;
|
|
33
|
+
noStore: boolean;
|
|
34
|
+
mustRevalidate: boolean;
|
|
35
|
+
proxyRevalidate: boolean;
|
|
36
|
+
public: boolean;
|
|
37
|
+
private: boolean;
|
|
38
|
+
immutable: boolean;
|
|
39
|
+
staleWhileRevalidate?: number;
|
|
40
|
+
staleIfError?: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Serializable metadata for a cached response.
|
|
44
|
+
*/
|
|
45
|
+
export interface CacheEntry {
|
|
46
|
+
/** Cache key (method + URL). */
|
|
47
|
+
key: string;
|
|
48
|
+
/** HTTP status code. */
|
|
49
|
+
status: number;
|
|
50
|
+
/** HTTP status text. */
|
|
51
|
+
statusText: string;
|
|
52
|
+
/** Response headers (normalized lowercase). */
|
|
53
|
+
headers: Record<string, string>;
|
|
54
|
+
/** Raw response body bytes. */
|
|
55
|
+
body: Buffer;
|
|
56
|
+
/** HTTP version string. */
|
|
57
|
+
httpVersion: string;
|
|
58
|
+
/** The final URL of the response. */
|
|
59
|
+
url: string;
|
|
60
|
+
/** Timestamp (ms since epoch) when the response was stored. */
|
|
61
|
+
storedAt: number;
|
|
62
|
+
/** ETag value from the response, if present. */
|
|
63
|
+
etag?: string;
|
|
64
|
+
/** Last-Modified value from the response, if present. */
|
|
65
|
+
lastModified?: string;
|
|
66
|
+
/** Parsed Cache-Control directives. */
|
|
67
|
+
directives: CacheDirectives;
|
|
68
|
+
/** The Vary header field names, lowercased. */
|
|
69
|
+
varyFields: string[];
|
|
70
|
+
/** The request headers that matched the Vary fields at storage time. */
|
|
71
|
+
varyHeaders: Record<string, string>;
|
|
72
|
+
/** Byte size of the body for LRU accounting. */
|
|
73
|
+
bodySize: number;
|
|
74
|
+
/** Timestamp (ms since epoch) when the entry was last accessed (for LRU). */
|
|
75
|
+
lastAccessedAt: number;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Describes a cache lookup result.
|
|
79
|
+
*/
|
|
80
|
+
export interface CacheLookupResult {
|
|
81
|
+
/** The matching cache entry, or undefined on a miss. */
|
|
82
|
+
entry?: CacheEntry;
|
|
83
|
+
/** Whether the entry is still fresh. */
|
|
84
|
+
fresh: boolean;
|
|
85
|
+
/** Whether the entry can be served stale while revalidating. */
|
|
86
|
+
staleWhileRevalidate: boolean;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Result of applying cache logic to decide request behavior.
|
|
90
|
+
*/
|
|
91
|
+
export interface CacheDecision {
|
|
92
|
+
/** If set, the cached response to serve directly. */
|
|
93
|
+
cachedResponse?: NLcURLResponse;
|
|
94
|
+
/** If set, conditional headers to add to the outgoing request. */
|
|
95
|
+
conditionalHeaders?: Record<string, string>;
|
|
96
|
+
/** Whether to store the response in cache after receiving it. */
|
|
97
|
+
shouldStore: boolean;
|
|
98
|
+
/** The cache entry that was matched (for 304 merging). */
|
|
99
|
+
matchedEntry?: CacheEntry;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cache/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,iFAAiF;IACjF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iGAAiG;IACjG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wDAAwD;IACxD,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,aAAa,GAAG,gBAAgB,CAAC;AAE/F;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,gCAAgC;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,wBAAwB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,wBAAwB;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,UAAU,EAAE,eAAe,CAAC;IAC5B,+CAA+C;IAC/C,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,wDAAwD;IACxD,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,wCAAwC;IACxC,KAAK,EAAE,OAAO,CAAC;IACf,gEAAgE;IAChE,oBAAoB,EAAE,OAAO,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,qDAAqD;IACrD,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,iEAAiE;IACjE,WAAW,EAAE,OAAO,CAAC;IACrB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,UAAU,CAAC;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/cache/types.ts"],"names":[],"mappings":""}
|
package/dist/cookies/jar.d.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { type Cookie } from "./parser.js";
|
|
2
|
+
export interface CookieJarOptions {
|
|
3
|
+
/** Maximum total cookies across all domains (default: 3000). */
|
|
4
|
+
maxCookies?: number;
|
|
5
|
+
/** Maximum cookies per domain (default: 180, matching Chrome). */
|
|
6
|
+
maxCookiesPerDomain?: number;
|
|
7
|
+
}
|
|
2
8
|
/**
|
|
3
9
|
* In-memory cookie store implementing RFC 6265 semantics. Manages cookie
|
|
4
10
|
* scoping by domain and path, enforces per-domain and global cookie limits,
|
|
@@ -6,6 +12,11 @@ import { type Cookie } from "./parser.js";
|
|
|
6
12
|
*/
|
|
7
13
|
export declare class CookieJar {
|
|
8
14
|
private cookies;
|
|
15
|
+
private readonly maxCookies;
|
|
16
|
+
private readonly maxCookiesPerDomain;
|
|
17
|
+
/** Monotonic counter for deterministic LRU ordering within the same ms. */
|
|
18
|
+
private accessCounter;
|
|
19
|
+
constructor(options?: CookieJarOptions);
|
|
9
20
|
/**
|
|
10
21
|
* Parses all `Set-Cookie` values from `headers` (or from `rawHeaders` when
|
|
11
22
|
* available to handle multiple `Set-Cookie` entries) and stores any valid
|
|
@@ -65,6 +76,15 @@ export declare class CookieJar {
|
|
|
65
76
|
*/
|
|
66
77
|
loadNetscapeString(content: string): void;
|
|
67
78
|
private store;
|
|
79
|
+
/**
|
|
80
|
+
* Evicts the least recently accessed cookie from a specific domain.
|
|
81
|
+
*/
|
|
82
|
+
private evictLRUForDomain;
|
|
83
|
+
/**
|
|
84
|
+
* Evicts one cookie globally, preferring the domain with the most cookies
|
|
85
|
+
* and then the least recently accessed cookie within that domain.
|
|
86
|
+
*/
|
|
87
|
+
private evictGlobalLRU;
|
|
68
88
|
private matches;
|
|
69
89
|
private domainMatches;
|
|
70
90
|
private pathMatches;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jar.d.ts","sourceRoot":"","sources":["../../src/cookies/jar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAK5E;;;;GAIG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAgB;
|
|
1
|
+
{"version":3,"file":"jar.d.ts","sourceRoot":"","sources":["../../src/cookies/jar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoC,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AAK5E,MAAM,WAAW,gBAAgB;IAC/B,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;GAIG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,2EAA2E;IAC3E,OAAO,CAAC,aAAa,CAAK;gBAEd,OAAO,CAAC,EAAE,gBAAgB;IAKtC;;;;;;;;OAQG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI;IAWxG;;;;;;;;OAQG;IACH,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM;IAiBjC;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;;;OAIG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIjC;;;;;OAKG;IACH,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC;IAI5B;;;;OAIG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;OAKG;IACH,gBAAgB,IAAI,MAAM;IAmB1B;;;;;;OAMG;IACH,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IA2BzC,OAAO,CAAC,KAAK;IAuBb;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAazB;;;OAGG;IACH,OAAO,CAAC,cAAc;IAsBtB,OAAO,CAAC,OAAO;IAgBf,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,sBAAsB;CAY/B"}
|
package/dist/cookies/jar.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { parseSetCookie, serializeCookies } from "./parser.js";
|
|
2
|
-
const
|
|
3
|
-
const
|
|
2
|
+
const DEFAULT_MAX_COOKIES = 3000;
|
|
3
|
+
const DEFAULT_MAX_COOKIES_PER_DOMAIN = 180;
|
|
4
4
|
/**
|
|
5
5
|
* In-memory cookie store implementing RFC 6265 semantics. Manages cookie
|
|
6
6
|
* scoping by domain and path, enforces per-domain and global cookie limits,
|
|
@@ -8,6 +8,14 @@ const MAX_COOKIES_PER_DOMAIN = 50;
|
|
|
8
8
|
*/
|
|
9
9
|
export class CookieJar {
|
|
10
10
|
cookies = [];
|
|
11
|
+
maxCookies;
|
|
12
|
+
maxCookiesPerDomain;
|
|
13
|
+
/** Monotonic counter for deterministic LRU ordering within the same ms. */
|
|
14
|
+
accessCounter = 0;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.maxCookies = options?.maxCookies ?? DEFAULT_MAX_COOKIES;
|
|
17
|
+
this.maxCookiesPerDomain = options?.maxCookiesPerDomain ?? DEFAULT_MAX_COOKIES_PER_DOMAIN;
|
|
18
|
+
}
|
|
11
19
|
/**
|
|
12
20
|
* Parses all `Set-Cookie` values from `headers` (or from `rawHeaders` when
|
|
13
21
|
* available to handle multiple `Set-Cookie` entries) and stores any valid
|
|
@@ -40,6 +48,9 @@ export class CookieJar {
|
|
|
40
48
|
const matching = this.cookies.filter((c) => this.matches(c, url, now));
|
|
41
49
|
if (matching.length === 0)
|
|
42
50
|
return "";
|
|
51
|
+
for (const c of matching) {
|
|
52
|
+
c.lastAccessedAt = ++this.accessCounter;
|
|
53
|
+
}
|
|
43
54
|
matching.sort((a, b) => {
|
|
44
55
|
if (a.path.length !== b.path.length)
|
|
45
56
|
return b.path.length - a.path.length;
|
|
@@ -91,6 +102,7 @@ export class CookieJar {
|
|
|
91
102
|
const includeSubdomains = domain.startsWith(".") ? "TRUE" : "FALSE";
|
|
92
103
|
const path = c.path || "/";
|
|
93
104
|
const secure = c.secure ? "TRUE" : "FALSE";
|
|
105
|
+
const httpOnly = c.httpOnly ? "TRUE" : "FALSE";
|
|
94
106
|
let expires = "0";
|
|
95
107
|
if (c.maxAge !== undefined) {
|
|
96
108
|
expires = String(Math.floor((c.createdAt + c.maxAge * 1000) / 1000));
|
|
@@ -98,7 +110,7 @@ export class CookieJar {
|
|
|
98
110
|
else if (c.expires) {
|
|
99
111
|
expires = String(Math.floor(c.expires.getTime() / 1000));
|
|
100
112
|
}
|
|
101
|
-
lines.push(`${domain}\t${includeSubdomains}\t${path}\t${secure}\t${expires}\t${c.name}\t${c.value}`);
|
|
113
|
+
lines.push(`${domain}\t${includeSubdomains}\t${path}\t${secure}\t${expires}\t${c.name}\t${c.value}\t${httpOnly}`);
|
|
102
114
|
}
|
|
103
115
|
return lines.join("\n") + "\n";
|
|
104
116
|
}
|
|
@@ -118,15 +130,17 @@ export class CookieJar {
|
|
|
118
130
|
if (parts.length < 7)
|
|
119
131
|
continue;
|
|
120
132
|
const [domain, , path, secure, expires, name, value] = parts;
|
|
133
|
+
const httpOnlyField = parts[7];
|
|
121
134
|
const cookie = {
|
|
122
135
|
name: name,
|
|
123
136
|
value: value,
|
|
124
137
|
domain: domain.startsWith(".") ? domain.slice(1) : domain,
|
|
125
138
|
path: path,
|
|
126
139
|
secure: secure === "TRUE",
|
|
127
|
-
httpOnly:
|
|
140
|
+
httpOnly: httpOnlyField === "TRUE",
|
|
128
141
|
sameSite: undefined,
|
|
129
142
|
createdAt: Date.now(),
|
|
143
|
+
lastAccessedAt: Date.now(),
|
|
130
144
|
};
|
|
131
145
|
const expiresNum = parseInt(expires, 10);
|
|
132
146
|
if (expiresNum > 0) {
|
|
@@ -142,21 +156,61 @@ export class CookieJar {
|
|
|
142
156
|
}
|
|
143
157
|
const idx = this.cookies.findIndex((c) => c.name === cookie.name && c.domain === cookie.domain && c.path === cookie.path);
|
|
144
158
|
if (idx >= 0) {
|
|
159
|
+
cookie.lastAccessedAt = this.cookies[idx].lastAccessedAt;
|
|
145
160
|
this.cookies[idx] = cookie;
|
|
146
161
|
}
|
|
147
162
|
else {
|
|
163
|
+
cookie.lastAccessedAt = ++this.accessCounter;
|
|
148
164
|
const domainCount = this.cookies.filter((c) => c.domain === cookie.domain).length;
|
|
149
|
-
if (domainCount >=
|
|
150
|
-
|
|
151
|
-
if (oldest >= 0)
|
|
152
|
-
this.cookies.splice(oldest, 1);
|
|
165
|
+
if (domainCount >= this.maxCookiesPerDomain) {
|
|
166
|
+
this.evictLRUForDomain(cookie.domain);
|
|
153
167
|
}
|
|
154
|
-
if (this.cookies.length >=
|
|
155
|
-
this.
|
|
168
|
+
if (this.cookies.length >= this.maxCookies) {
|
|
169
|
+
this.evictGlobalLRU();
|
|
156
170
|
}
|
|
157
171
|
this.cookies.push(cookie);
|
|
158
172
|
}
|
|
159
173
|
}
|
|
174
|
+
/**
|
|
175
|
+
* Evicts the least recently accessed cookie from a specific domain.
|
|
176
|
+
*/
|
|
177
|
+
evictLRUForDomain(domain) {
|
|
178
|
+
let lruIdx = -1;
|
|
179
|
+
let lruTime = Infinity;
|
|
180
|
+
for (let i = 0; i < this.cookies.length; i++) {
|
|
181
|
+
const c = this.cookies[i];
|
|
182
|
+
if (c.domain === domain && c.lastAccessedAt < lruTime) {
|
|
183
|
+
lruTime = c.lastAccessedAt;
|
|
184
|
+
lruIdx = i;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (lruIdx >= 0)
|
|
188
|
+
this.cookies.splice(lruIdx, 1);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Evicts one cookie globally, preferring the domain with the most cookies
|
|
192
|
+
* and then the least recently accessed cookie within that domain.
|
|
193
|
+
*/
|
|
194
|
+
evictGlobalLRU() {
|
|
195
|
+
const domainCounts = new Map();
|
|
196
|
+
for (const c of this.cookies) {
|
|
197
|
+
domainCounts.set(c.domain, (domainCounts.get(c.domain) ?? 0) + 1);
|
|
198
|
+
}
|
|
199
|
+
let fatDomain = "";
|
|
200
|
+
let fatCount = 0;
|
|
201
|
+
for (const [d, count] of domainCounts) {
|
|
202
|
+
if (count > fatCount) {
|
|
203
|
+
fatCount = count;
|
|
204
|
+
fatDomain = d;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (fatDomain) {
|
|
208
|
+
this.evictLRUForDomain(fatDomain);
|
|
209
|
+
}
|
|
210
|
+
else if (this.cookies.length > 0) {
|
|
211
|
+
this.cookies.shift();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
160
214
|
matches(cookie, url, now) {
|
|
161
215
|
if (cookie.maxAge !== undefined) {
|
|
162
216
|
if (now > cookie.createdAt + cookie.maxAge * 1000)
|
package/dist/cookies/jar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jar.js","sourceRoot":"","sources":["../../src/cookies/jar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAe,MAAM,aAAa,CAAC;AAE5E,MAAM,
|
|
1
|
+
{"version":3,"file":"jar.js","sourceRoot":"","sources":["../../src/cookies/jar.ts"],"names":[],"mappings":"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"}
|
package/dist/cookies/parser.d.ts
CHANGED
|
@@ -24,17 +24,9 @@ export interface Cookie {
|
|
|
24
24
|
httpOnly: boolean;
|
|
25
25
|
sameSite?: "strict" | "lax" | "none";
|
|
26
26
|
createdAt: number;
|
|
27
|
+
/** Timestamp (ms) when the cookie was last matched in getCookieHeader() for LRU eviction. */
|
|
28
|
+
lastAccessedAt: number;
|
|
27
29
|
}
|
|
28
|
-
/**
|
|
29
|
-
* Parses a `Set-Cookie` header value into a {@link Cookie} object.
|
|
30
|
-
* Validates the cookie against the request URL to enforce domain and path
|
|
31
|
-
* scoping rules per RFC 6265.
|
|
32
|
-
*
|
|
33
|
-
* @param {string} header - Raw `Set-Cookie` header value.
|
|
34
|
-
* @param {URL} requestUrl - URL of the request that received the header.
|
|
35
|
-
* @returns {Cookie | null} Parsed cookie, or `null` if the header is invalid or
|
|
36
|
-
* the domain attribute fails validation against the request origin.
|
|
37
|
-
*/
|
|
38
30
|
export declare function parseSetCookie(header: string, requestUrl: URL): Cookie | null;
|
|
39
31
|
/**
|
|
40
32
|
* Serializes an array of cookies into the `Cookie` request header value.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/cookies/parser.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/cookies/parser.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,6FAA6F;IAC7F,cAAc,EAAE,MAAM,CAAC;CACxB;AA0BD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,GAAG,MAAM,GAAG,IAAI,CAuG7E;AASD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAE1D"}
|
package/dist/cookies/parser.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isPublicSuffix } from "./public-suffix.js";
|
|
1
2
|
/**
|
|
2
3
|
* Parses a `Set-Cookie` header value into a {@link Cookie} object.
|
|
3
4
|
* Validates the cookie against the request URL to enforce domain and path
|
|
@@ -8,6 +9,17 @@
|
|
|
8
9
|
* @returns {Cookie | null} Parsed cookie, or `null` if the header is invalid or
|
|
9
10
|
* the domain attribute fails validation against the request origin.
|
|
10
11
|
*/
|
|
12
|
+
const COOKIE_NAME_RE = /^[!#$%&'*+\-.^_`|~\w]+$/;
|
|
13
|
+
const COOKIE_VALUE_CTL_RE = /[\x00-\x1f\x7f]/;
|
|
14
|
+
const MAX_COOKIE_SIZE = 4096;
|
|
15
|
+
const VALID_SAMESITE = new Set(["strict", "lax", "none"]);
|
|
16
|
+
/** Returns true if the string looks like an IPv4 or IPv6 address. */
|
|
17
|
+
function looksLikeIP(host) {
|
|
18
|
+
if (host.includes(":"))
|
|
19
|
+
return true;
|
|
20
|
+
const parts = host.split(".");
|
|
21
|
+
return parts.length === 4 && parts.every((p) => /^\d{1,3}$/.test(p));
|
|
22
|
+
}
|
|
11
23
|
export function parseSetCookie(header, requestUrl) {
|
|
12
24
|
const parts = header.split(";").map((s) => s.trim());
|
|
13
25
|
if (parts.length === 0)
|
|
@@ -20,6 +32,12 @@ export function parseSetCookie(header, requestUrl) {
|
|
|
20
32
|
const value = nameValue.substring(eqIdx + 1).trim();
|
|
21
33
|
if (!name)
|
|
22
34
|
return null;
|
|
35
|
+
if (!COOKIE_NAME_RE.test(name))
|
|
36
|
+
return null;
|
|
37
|
+
if (COOKIE_VALUE_CTL_RE.test(value))
|
|
38
|
+
return null;
|
|
39
|
+
if (name.length + value.length > MAX_COOKIE_SIZE)
|
|
40
|
+
return null;
|
|
23
41
|
const cookie = {
|
|
24
42
|
name,
|
|
25
43
|
value,
|
|
@@ -28,6 +46,7 @@ export function parseSetCookie(header, requestUrl) {
|
|
|
28
46
|
secure: false,
|
|
29
47
|
httpOnly: false,
|
|
30
48
|
createdAt: Date.now(),
|
|
49
|
+
lastAccessedAt: Date.now(),
|
|
31
50
|
};
|
|
32
51
|
for (let i = 1; i < parts.length; i++) {
|
|
33
52
|
const attr = parts[i];
|
|
@@ -40,9 +59,18 @@ export function parseSetCookie(header, requestUrl) {
|
|
|
40
59
|
if (d.startsWith("."))
|
|
41
60
|
d = d.substring(1);
|
|
42
61
|
const host = requestUrl.hostname.toLowerCase();
|
|
62
|
+
if (looksLikeIP(d) || looksLikeIP(host)) {
|
|
63
|
+
if (d !== host)
|
|
64
|
+
return null;
|
|
65
|
+
cookie.domain = d;
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
43
68
|
if (d !== host && !host.endsWith("." + d)) {
|
|
44
69
|
return null;
|
|
45
70
|
}
|
|
71
|
+
if (isPublicSuffix(d)) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
46
74
|
cookie.domain = d;
|
|
47
75
|
break;
|
|
48
76
|
}
|
|
@@ -69,11 +97,30 @@ export function parseSetCookie(header, requestUrl) {
|
|
|
69
97
|
case "httponly":
|
|
70
98
|
cookie.httpOnly = true;
|
|
71
99
|
break;
|
|
72
|
-
case "samesite":
|
|
73
|
-
|
|
100
|
+
case "samesite": {
|
|
101
|
+
const sv = attrValue.toLowerCase();
|
|
102
|
+
if (VALID_SAMESITE.has(sv)) {
|
|
103
|
+
cookie.sameSite = sv;
|
|
104
|
+
}
|
|
74
105
|
break;
|
|
106
|
+
}
|
|
75
107
|
}
|
|
76
108
|
}
|
|
109
|
+
if (cookie.sameSite === undefined) {
|
|
110
|
+
cookie.sameSite = "lax";
|
|
111
|
+
}
|
|
112
|
+
if (cookie.name.startsWith("__Host-")) {
|
|
113
|
+
if (!cookie.secure)
|
|
114
|
+
return null;
|
|
115
|
+
if (cookie.domain !== requestUrl.hostname.toLowerCase())
|
|
116
|
+
return null;
|
|
117
|
+
if (cookie.path !== "/")
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
if (cookie.name.startsWith("__Secure-")) {
|
|
121
|
+
if (!cookie.secure)
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
77
124
|
return cookie;
|
|
78
125
|
}
|
|
79
126
|
function defaultPath(path) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/cookies/parser.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/cookies/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AUTO-GENERATED — DO NOT EDIT MANUALLY.
|
|
3
|
+
*
|
|
4
|
+
* Complete Mozilla Public Suffix List rules.
|
|
5
|
+
* Generated from: https://publicsuffix.org/list/public_suffix_list.dat
|
|
6
|
+
* Generated on: 2026-03-08T17:40:31.403Z
|
|
7
|
+
* Total rules: 10153
|
|
8
|
+
*
|
|
9
|
+
* To regenerate: npx tsx scripts/update-psl.ts
|
|
10
|
+
*/
|
|
11
|
+
export declare const PSL_RULES: readonly string[];
|
|
12
|
+
//# sourceMappingURL=psl-data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"psl-data.d.ts","sourceRoot":"","sources":["../../src/cookies/psl-data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,eAAO,MAAM,SAAS,EAAE,SAAS,MAAM,EA06TtC,CAAC"}
|