nlcurl 0.1.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 (199) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +162 -0
  3. package/dist/cli/args.d.ts +42 -0
  4. package/dist/cli/args.d.ts.map +1 -0
  5. package/dist/cli/args.js +262 -0
  6. package/dist/cli/args.js.map +1 -0
  7. package/dist/cli/index.d.ts +8 -0
  8. package/dist/cli/index.d.ts.map +1 -0
  9. package/dist/cli/index.js +114 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/cli/output.d.ts +22 -0
  12. package/dist/cli/output.d.ts.map +1 -0
  13. package/dist/cli/output.js +105 -0
  14. package/dist/cli/output.js.map +1 -0
  15. package/dist/cookies/jar.d.ts +41 -0
  16. package/dist/cookies/jar.d.ts.map +1 -0
  17. package/dist/cookies/jar.js +148 -0
  18. package/dist/cookies/jar.js.map +1 -0
  19. package/dist/cookies/parser.d.ts +24 -0
  20. package/dist/cookies/parser.d.ts.map +1 -0
  21. package/dist/cookies/parser.js +93 -0
  22. package/dist/cookies/parser.js.map +1 -0
  23. package/dist/core/client.d.ts +79 -0
  24. package/dist/core/client.d.ts.map +1 -0
  25. package/dist/core/client.js +106 -0
  26. package/dist/core/client.js.map +1 -0
  27. package/dist/core/errors.d.ts +36 -0
  28. package/dist/core/errors.d.ts.map +1 -0
  29. package/dist/core/errors.js +65 -0
  30. package/dist/core/errors.js.map +1 -0
  31. package/dist/core/request.d.ts +96 -0
  32. package/dist/core/request.d.ts.map +1 -0
  33. package/dist/core/request.js +5 -0
  34. package/dist/core/request.js.map +1 -0
  35. package/dist/core/response.d.ts +48 -0
  36. package/dist/core/response.d.ts.map +1 -0
  37. package/dist/core/response.js +65 -0
  38. package/dist/core/response.js.map +1 -0
  39. package/dist/core/session.d.ts +60 -0
  40. package/dist/core/session.d.ts.map +1 -0
  41. package/dist/core/session.js +305 -0
  42. package/dist/core/session.js.map +1 -0
  43. package/dist/fingerprints/akamai.d.ts +17 -0
  44. package/dist/fingerprints/akamai.d.ts.map +1 -0
  45. package/dist/fingerprints/akamai.js +30 -0
  46. package/dist/fingerprints/akamai.js.map +1 -0
  47. package/dist/fingerprints/database.d.ts +33 -0
  48. package/dist/fingerprints/database.d.ts.map +1 -0
  49. package/dist/fingerprints/database.js +68 -0
  50. package/dist/fingerprints/database.js.map +1 -0
  51. package/dist/fingerprints/extensions.d.ts +49 -0
  52. package/dist/fingerprints/extensions.d.ts.map +1 -0
  53. package/dist/fingerprints/extensions.js +178 -0
  54. package/dist/fingerprints/extensions.js.map +1 -0
  55. package/dist/fingerprints/ja3.d.ts +32 -0
  56. package/dist/fingerprints/ja3.d.ts.map +1 -0
  57. package/dist/fingerprints/ja3.js +64 -0
  58. package/dist/fingerprints/ja3.js.map +1 -0
  59. package/dist/fingerprints/profiles/chrome.d.ts +30 -0
  60. package/dist/fingerprints/profiles/chrome.d.ts.map +1 -0
  61. package/dist/fingerprints/profiles/chrome.js +202 -0
  62. package/dist/fingerprints/profiles/chrome.js.map +1 -0
  63. package/dist/fingerprints/profiles/edge.d.ts +16 -0
  64. package/dist/fingerprints/profiles/edge.d.ts.map +1 -0
  65. package/dist/fingerprints/profiles/edge.js +61 -0
  66. package/dist/fingerprints/profiles/edge.js.map +1 -0
  67. package/dist/fingerprints/profiles/firefox.d.ts +13 -0
  68. package/dist/fingerprints/profiles/firefox.d.ts.map +1 -0
  69. package/dist/fingerprints/profiles/firefox.js +160 -0
  70. package/dist/fingerprints/profiles/firefox.js.map +1 -0
  71. package/dist/fingerprints/profiles/safari.d.ts +16 -0
  72. package/dist/fingerprints/profiles/safari.d.ts.map +1 -0
  73. package/dist/fingerprints/profiles/safari.js +140 -0
  74. package/dist/fingerprints/profiles/safari.js.map +1 -0
  75. package/dist/fingerprints/profiles/tor.d.ts +14 -0
  76. package/dist/fingerprints/profiles/tor.d.ts.map +1 -0
  77. package/dist/fingerprints/profiles/tor.js +136 -0
  78. package/dist/fingerprints/profiles/tor.js.map +1 -0
  79. package/dist/fingerprints/types.d.ts +104 -0
  80. package/dist/fingerprints/types.d.ts.map +1 -0
  81. package/dist/fingerprints/types.js +9 -0
  82. package/dist/fingerprints/types.js.map +1 -0
  83. package/dist/http/h1/client.d.ts +21 -0
  84. package/dist/http/h1/client.d.ts.map +1 -0
  85. package/dist/http/h1/client.js +136 -0
  86. package/dist/http/h1/client.js.map +1 -0
  87. package/dist/http/h1/encoder.d.ts +11 -0
  88. package/dist/http/h1/encoder.d.ts.map +1 -0
  89. package/dist/http/h1/encoder.js +75 -0
  90. package/dist/http/h1/encoder.js.map +1 -0
  91. package/dist/http/h1/parser.d.ts +61 -0
  92. package/dist/http/h1/parser.d.ts.map +1 -0
  93. package/dist/http/h1/parser.js +258 -0
  94. package/dist/http/h1/parser.js.map +1 -0
  95. package/dist/http/h2/client.d.ts +48 -0
  96. package/dist/http/h2/client.d.ts.map +1 -0
  97. package/dist/http/h2/client.js +376 -0
  98. package/dist/http/h2/client.js.map +1 -0
  99. package/dist/http/h2/frames.d.ts +65 -0
  100. package/dist/http/h2/frames.d.ts.map +1 -0
  101. package/dist/http/h2/frames.js +184 -0
  102. package/dist/http/h2/frames.js.map +1 -0
  103. package/dist/http/h2/hpack.d.ts +27 -0
  104. package/dist/http/h2/hpack.d.ts.map +1 -0
  105. package/dist/http/h2/hpack.js +423 -0
  106. package/dist/http/h2/hpack.js.map +1 -0
  107. package/dist/http/negotiator.d.ts +36 -0
  108. package/dist/http/negotiator.d.ts.map +1 -0
  109. package/dist/http/negotiator.js +101 -0
  110. package/dist/http/negotiator.js.map +1 -0
  111. package/dist/http/pool.d.ts +63 -0
  112. package/dist/http/pool.d.ts.map +1 -0
  113. package/dist/http/pool.js +177 -0
  114. package/dist/http/pool.js.map +1 -0
  115. package/dist/index.d.ts +22 -0
  116. package/dist/index.d.ts.map +1 -0
  117. package/dist/index.js +23 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/middleware/interceptor.d.ts +27 -0
  120. package/dist/middleware/interceptor.d.ts.map +1 -0
  121. package/dist/middleware/interceptor.js +35 -0
  122. package/dist/middleware/interceptor.js.map +1 -0
  123. package/dist/middleware/rate-limiter.d.ts +26 -0
  124. package/dist/middleware/rate-limiter.d.ts.map +1 -0
  125. package/dist/middleware/rate-limiter.js +59 -0
  126. package/dist/middleware/rate-limiter.js.map +1 -0
  127. package/dist/middleware/retry.d.ts +17 -0
  128. package/dist/middleware/retry.d.ts.map +1 -0
  129. package/dist/middleware/retry.js +64 -0
  130. package/dist/middleware/retry.js.map +1 -0
  131. package/dist/proxy/http-proxy.d.ts +23 -0
  132. package/dist/proxy/http-proxy.d.ts.map +1 -0
  133. package/dist/proxy/http-proxy.js +93 -0
  134. package/dist/proxy/http-proxy.js.map +1 -0
  135. package/dist/proxy/socks.d.ts +24 -0
  136. package/dist/proxy/socks.d.ts.map +1 -0
  137. package/dist/proxy/socks.js +196 -0
  138. package/dist/proxy/socks.js.map +1 -0
  139. package/dist/tls/constants.d.ts +142 -0
  140. package/dist/tls/constants.d.ts.map +1 -0
  141. package/dist/tls/constants.js +163 -0
  142. package/dist/tls/constants.js.map +1 -0
  143. package/dist/tls/node-engine.d.ts +22 -0
  144. package/dist/tls/node-engine.d.ts.map +1 -0
  145. package/dist/tls/node-engine.js +190 -0
  146. package/dist/tls/node-engine.js.map +1 -0
  147. package/dist/tls/stealth/client-hello.d.ts +38 -0
  148. package/dist/tls/stealth/client-hello.d.ts.map +1 -0
  149. package/dist/tls/stealth/client-hello.js +197 -0
  150. package/dist/tls/stealth/client-hello.js.map +1 -0
  151. package/dist/tls/stealth/engine.d.ts +16 -0
  152. package/dist/tls/stealth/engine.d.ts.map +1 -0
  153. package/dist/tls/stealth/engine.js +196 -0
  154. package/dist/tls/stealth/engine.js.map +1 -0
  155. package/dist/tls/stealth/handshake.d.ts +45 -0
  156. package/dist/tls/stealth/handshake.d.ts.map +1 -0
  157. package/dist/tls/stealth/handshake.js +403 -0
  158. package/dist/tls/stealth/handshake.js.map +1 -0
  159. package/dist/tls/stealth/key-schedule.d.ts +85 -0
  160. package/dist/tls/stealth/key-schedule.d.ts.map +1 -0
  161. package/dist/tls/stealth/key-schedule.js +141 -0
  162. package/dist/tls/stealth/key-schedule.js.map +1 -0
  163. package/dist/tls/stealth/record-layer.d.ts +74 -0
  164. package/dist/tls/stealth/record-layer.d.ts.map +1 -0
  165. package/dist/tls/stealth/record-layer.js +167 -0
  166. package/dist/tls/stealth/record-layer.js.map +1 -0
  167. package/dist/tls/types.d.ts +58 -0
  168. package/dist/tls/types.d.ts.map +1 -0
  169. package/dist/tls/types.js +6 -0
  170. package/dist/tls/types.js.map +1 -0
  171. package/dist/utils/buffer-reader.d.ts +32 -0
  172. package/dist/utils/buffer-reader.d.ts.map +1 -0
  173. package/dist/utils/buffer-reader.js +99 -0
  174. package/dist/utils/buffer-reader.js.map +1 -0
  175. package/dist/utils/buffer-writer.d.ts +35 -0
  176. package/dist/utils/buffer-writer.d.ts.map +1 -0
  177. package/dist/utils/buffer-writer.js +121 -0
  178. package/dist/utils/buffer-writer.js.map +1 -0
  179. package/dist/utils/encoding.d.ts +19 -0
  180. package/dist/utils/encoding.d.ts.map +1 -0
  181. package/dist/utils/encoding.js +63 -0
  182. package/dist/utils/encoding.js.map +1 -0
  183. package/dist/utils/logger.d.ts +24 -0
  184. package/dist/utils/logger.d.ts.map +1 -0
  185. package/dist/utils/logger.js +56 -0
  186. package/dist/utils/logger.js.map +1 -0
  187. package/dist/utils/url.d.ts +22 -0
  188. package/dist/utils/url.d.ts.map +1 -0
  189. package/dist/utils/url.js +56 -0
  190. package/dist/utils/url.js.map +1 -0
  191. package/dist/ws/client.d.ts +63 -0
  192. package/dist/ws/client.d.ts.map +1 -0
  193. package/dist/ws/client.js +273 -0
  194. package/dist/ws/client.js.map +1 -0
  195. package/dist/ws/frame.d.ts +44 -0
  196. package/dist/ws/frame.d.ts.map +1 -0
  197. package/dist/ws/frame.js +146 -0
  198. package/dist/ws/frame.js.map +1 -0
  199. package/package.json +57 -0
@@ -0,0 +1,21 @@
1
+ /**
2
+ * HTTP/1.1 client.
3
+ *
4
+ * Sends requests and receives responses over a TLS (or plain TCP)
5
+ * Duplex stream. Supports connection reuse (keep-alive).
6
+ */
7
+ import type { Duplex } from 'node:stream';
8
+ import type { NLcURLRequest } from '../../core/request.js';
9
+ import { NLcURLResponse } from '../../core/response.js';
10
+ import type { RequestTimings } from '../../core/request.js';
11
+ export interface H1ClientOptions {
12
+ /** Default headers to merge with each request. */
13
+ defaultHeaders?: Array<[string, string]>;
14
+ }
15
+ /**
16
+ * Send a single HTTP/1.1 request over an already-connected stream.
17
+ *
18
+ * Returns a fully parsed NLcURLResponse.
19
+ */
20
+ export declare function sendH1Request(stream: Duplex, request: NLcURLRequest, options?: H1ClientOptions, timings?: Partial<RequestTimings>): Promise<NLcURLResponse>;
21
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/http/h1/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAKxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,cAAc,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CAC1C;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,eAAoB,EAC7B,OAAO,GAAE,OAAO,CAAC,cAAc,CAAM,GACpC,OAAO,CAAC,cAAc,CAAC,CAyDzB"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * HTTP/1.1 client.
3
+ *
4
+ * Sends requests and receives responses over a TLS (or plain TCP)
5
+ * Duplex stream. Supports connection reuse (keep-alive).
6
+ */
7
+ import { NLcURLResponse } from '../../core/response.js';
8
+ import { HTTPError, TimeoutError } from '../../core/errors.js';
9
+ import { encodeRequest } from './encoder.js';
10
+ import { HttpResponseParser } from './parser.js';
11
+ import { decompressBody } from '../../utils/encoding.js';
12
+ /**
13
+ * Send a single HTTP/1.1 request over an already-connected stream.
14
+ *
15
+ * Returns a fully parsed NLcURLResponse.
16
+ */
17
+ export async function sendH1Request(stream, request, options = {}, timings = {}) {
18
+ const encoded = encodeRequest(request, options.defaultHeaders ?? []);
19
+ // Write request
20
+ await new Promise((resolve, reject) => {
21
+ stream.write(encoded, (err) => {
22
+ if (err)
23
+ reject(new HTTPError(err.message, 0));
24
+ else
25
+ resolve();
26
+ });
27
+ });
28
+ // Read response
29
+ const parser = new HttpResponseParser(request.method ?? 'GET');
30
+ const parsed = await readResponse(stream, parser, request);
31
+ const firstByteTime = Date.now();
32
+ if (timings.connect) {
33
+ timings.firstByte = firstByteTime - timings.connect;
34
+ }
35
+ // Decompress body
36
+ const encoding = parsed.headers.get('content-encoding');
37
+ let body;
38
+ if (encoding) {
39
+ body = await decompressBody(parsed.body, encoding);
40
+ }
41
+ else {
42
+ body = parsed.body;
43
+ }
44
+ // Build response headers
45
+ const responseHeaders = {};
46
+ for (const [k, v] of parsed.headers) {
47
+ responseHeaders[k] = v;
48
+ }
49
+ return new NLcURLResponse({
50
+ status: parsed.statusCode,
51
+ statusText: parsed.statusMessage,
52
+ headers: responseHeaders,
53
+ rawHeaders: parsed.rawHeaders.map(([k, v]) => [k.toLowerCase(), v]),
54
+ rawBody: body,
55
+ httpVersion: parsed.httpVersion,
56
+ url: request.url,
57
+ redirectCount: 0,
58
+ timings: {
59
+ dns: timings.dns ?? 0,
60
+ connect: timings.connect ?? 0,
61
+ tls: timings.tls ?? 0,
62
+ firstByte: timings.firstByte ?? 0,
63
+ total: 0, // Filled after return
64
+ },
65
+ request: {
66
+ url: request.url,
67
+ method: request.method ?? 'GET',
68
+ headers: request.headers ?? {},
69
+ },
70
+ });
71
+ }
72
+ // ---- Internals ----
73
+ function readResponse(stream, parser, request) {
74
+ return new Promise((resolve, reject) => {
75
+ let settled = false;
76
+ let timer;
77
+ const timeout = request.timeout;
78
+ const timeoutMs = typeof timeout === 'number' ? timeout : (timeout?.total ?? timeout?.response ?? 0);
79
+ if (timeoutMs > 0) {
80
+ timer = setTimeout(() => {
81
+ if (!settled) {
82
+ settled = true;
83
+ cleanup();
84
+ reject(new TimeoutError('Response timed out', 'response'));
85
+ }
86
+ }, timeoutMs);
87
+ }
88
+ const onData = (chunk) => {
89
+ try {
90
+ if (parser.feed(chunk)) {
91
+ settled = true;
92
+ cleanup();
93
+ resolve(parser.getResult());
94
+ }
95
+ }
96
+ catch (err) {
97
+ settled = true;
98
+ cleanup();
99
+ reject(err);
100
+ }
101
+ };
102
+ const onEnd = () => {
103
+ if (!settled) {
104
+ parser.connectionClosed();
105
+ try {
106
+ settled = true;
107
+ cleanup();
108
+ resolve(parser.getResult());
109
+ }
110
+ catch {
111
+ settled = true;
112
+ cleanup();
113
+ reject(new HTTPError('Connection closed before response complete', 0));
114
+ }
115
+ }
116
+ };
117
+ const onError = (err) => {
118
+ if (!settled) {
119
+ settled = true;
120
+ cleanup();
121
+ reject(new HTTPError(err.message, 0));
122
+ }
123
+ };
124
+ const cleanup = () => {
125
+ if (timer)
126
+ clearTimeout(timer);
127
+ stream.removeListener('data', onData);
128
+ stream.removeListener('end', onEnd);
129
+ stream.removeListener('error', onError);
130
+ };
131
+ stream.on('data', onData);
132
+ stream.once('end', onEnd);
133
+ stream.once('error', onError);
134
+ });
135
+ }
136
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/http/h1/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * HTTP/1.1 request encoder.
3
+ *
4
+ * Serializes NLcURLRequest objects into raw HTTP/1.1 wire format.
5
+ */
6
+ import type { NLcURLRequest } from '../../core/request.js';
7
+ /**
8
+ * Encode an HTTP/1.1 request to a Buffer ready to write to a socket.
9
+ */
10
+ export declare function encodeRequest(request: NLcURLRequest, defaultHeaders: Array<[string, string]>): Buffer;
11
+ //# sourceMappingURL=encoder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../src/http/h1/encoder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,uBAAuB,CAAC;AAExE;;GAEG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,aAAa,EACtB,cAAc,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACtC,MAAM,CA0DR"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * HTTP/1.1 request encoder.
3
+ *
4
+ * Serializes NLcURLRequest objects into raw HTTP/1.1 wire format.
5
+ */
6
+ /**
7
+ * Encode an HTTP/1.1 request to a Buffer ready to write to a socket.
8
+ */
9
+ export function encodeRequest(request, defaultHeaders) {
10
+ const url = new URL(request.url);
11
+ const path = url.pathname + url.search;
12
+ const host = url.port
13
+ ? `${url.hostname}:${url.port}`
14
+ : url.hostname;
15
+ const lines = [];
16
+ lines.push(`${request.method} ${path} HTTP/1.1`);
17
+ // Collect headers -- merge defaults under request headers
18
+ const headerMap = new Map();
19
+ // Apply default headers first (lowercase keys)
20
+ for (const [k, v] of defaultHeaders) {
21
+ headerMap.set(k.toLowerCase(), v);
22
+ }
23
+ // Host header
24
+ if (!headerMap.has('host')) {
25
+ headerMap.set('host', host);
26
+ }
27
+ // Apply request headers (override defaults)
28
+ if (request.headers) {
29
+ for (const [k, v] of Object.entries(request.headers)) {
30
+ headerMap.set(k.toLowerCase(), v);
31
+ }
32
+ }
33
+ // Body handling
34
+ let bodyBuffer;
35
+ if (request.body !== undefined && request.body !== null) {
36
+ bodyBuffer = serializeBody(request.body);
37
+ if (!headerMap.has('content-length')) {
38
+ headerMap.set('content-length', String(bodyBuffer.length));
39
+ }
40
+ if (!headerMap.has('content-type')) {
41
+ headerMap.set('content-type', 'application/x-www-form-urlencoded');
42
+ }
43
+ }
44
+ // Emit headers (validate against CRLF injection)
45
+ for (const [k, v] of headerMap) {
46
+ if (/[\r\n\0]/.test(k) || /[\r\n\0]/.test(v)) {
47
+ throw new Error(`Invalid header: name or value contains forbidden characters`);
48
+ }
49
+ lines.push(`${k}: ${v}`);
50
+ }
51
+ lines.push('');
52
+ lines.push('');
53
+ const head = Buffer.from(lines.join('\r\n'), 'latin1');
54
+ if (bodyBuffer) {
55
+ return Buffer.concat([head, bodyBuffer]);
56
+ }
57
+ return head;
58
+ }
59
+ function serializeBody(body) {
60
+ if (body === null || body === undefined)
61
+ return Buffer.alloc(0);
62
+ if (Buffer.isBuffer(body))
63
+ return body;
64
+ if (typeof body === 'string')
65
+ return Buffer.from(body, 'utf-8');
66
+ if (body instanceof URLSearchParams) {
67
+ return Buffer.from(body.toString(), 'utf-8');
68
+ }
69
+ if (typeof body === 'object' && !(body instanceof ReadableStream)) {
70
+ return Buffer.from(JSON.stringify(body), 'utf-8');
71
+ }
72
+ // ReadableStream: not supported in synchronous encoding
73
+ return Buffer.alloc(0);
74
+ }
75
+ //# sourceMappingURL=encoder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encoder.js","sourceRoot":"","sources":["../../../src/http/h1/encoder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * HTTP/1.1 response parser.
3
+ *
4
+ * Incrementally parses HTTP/1.1 responses from a byte stream.
5
+ * Handles chunked transfer encoding and content-length framing.
6
+ */
7
+ export interface ParsedResponse {
8
+ httpVersion: string;
9
+ statusCode: number;
10
+ statusMessage: string;
11
+ headers: Map<string, string>;
12
+ /** Raw header entries preserving order and case. */
13
+ rawHeaders: Array<[string, string]>;
14
+ body: Buffer;
15
+ }
16
+ /**
17
+ * Incremental HTTP/1.1 response parser.
18
+ */
19
+ export declare class HttpResponseParser {
20
+ private requestMethod;
21
+ private state;
22
+ private buffer;
23
+ private httpVersion;
24
+ private statusCode;
25
+ private statusMessage;
26
+ private headers;
27
+ private rawHeaders;
28
+ private contentLength;
29
+ private isChunked;
30
+ private bodyChunks;
31
+ private bodyBytesRead;
32
+ private result;
33
+ /** Maximum header section size (256 KB). */
34
+ private static readonly MAX_HEADER_SIZE;
35
+ /** Maximum body size (128 MB). */
36
+ private static readonly MAX_BODY_SIZE;
37
+ constructor(requestMethod?: string);
38
+ /**
39
+ * Feed data into the parser.
40
+ *
41
+ * Returns `true` when the response is fully parsed.
42
+ * After that, call `getResult()` to retrieve the parsed response,
43
+ * and `getRemainder()` for any trailing bytes.
44
+ */
45
+ feed(data: Buffer): boolean;
46
+ getResult(): ParsedResponse;
47
+ /** Get remaining data after the response (for connection reuse). */
48
+ getRemainder(): Buffer;
49
+ private parseStatusLine;
50
+ private parseHeaders;
51
+ private finalizeHeaders;
52
+ private parseBody;
53
+ private parseChunkedBody;
54
+ private finalize;
55
+ /**
56
+ * Signal that the connection was closed.
57
+ * Finalizes a "read until close" body.
58
+ */
59
+ connectionClosed(): void;
60
+ }
61
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../src/http/h1/parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,oDAAoD;IACpD,UAAU,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;CACd;AAUD;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,aAAa,CAAM;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,MAAM,CAA+B;IAE7C,4CAA4C;IAC5C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAU;IACjD,kCAAkC;IAClC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAa;gBAEtC,aAAa,SAAQ;IAIjC;;;;;;OAMG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAuB3B,SAAS,IAAI,cAAc;IAO3B,oEAAoE;IACpE,YAAY,IAAI,MAAM;IAItB,OAAO,CAAC,eAAe;IAwBvB,OAAO,CAAC,YAAY;IAsCpB,OAAO,CAAC,eAAe;IA8CvB,OAAO,CAAC,SAAS;IA6BjB,OAAO,CAAC,gBAAgB;IA4CxB,OAAO,CAAC,QAAQ;IAYhB;;;OAGG;IACH,gBAAgB,IAAI,IAAI;CAKzB"}
@@ -0,0 +1,258 @@
1
+ /**
2
+ * HTTP/1.1 response parser.
3
+ *
4
+ * Incrementally parses HTTP/1.1 responses from a byte stream.
5
+ * Handles chunked transfer encoding and content-length framing.
6
+ */
7
+ var ParserState;
8
+ (function (ParserState) {
9
+ ParserState[ParserState["StatusLine"] = 0] = "StatusLine";
10
+ ParserState[ParserState["Headers"] = 1] = "Headers";
11
+ ParserState[ParserState["Body"] = 2] = "Body";
12
+ ParserState[ParserState["ChunkedBody"] = 3] = "ChunkedBody";
13
+ ParserState[ParserState["Complete"] = 4] = "Complete";
14
+ })(ParserState || (ParserState = {}));
15
+ /**
16
+ * Incremental HTTP/1.1 response parser.
17
+ */
18
+ export class HttpResponseParser {
19
+ requestMethod;
20
+ state = ParserState.StatusLine;
21
+ buffer = Buffer.alloc(0);
22
+ httpVersion = '';
23
+ statusCode = 0;
24
+ statusMessage = '';
25
+ headers = new Map();
26
+ rawHeaders = [];
27
+ contentLength = -1;
28
+ isChunked = false;
29
+ bodyChunks = [];
30
+ bodyBytesRead = 0;
31
+ result = null;
32
+ /** Maximum header section size (256 KB). */
33
+ static MAX_HEADER_SIZE = 262144;
34
+ /** Maximum body size (128 MB). */
35
+ static MAX_BODY_SIZE = 134217728;
36
+ constructor(requestMethod = 'GET') {
37
+ this.requestMethod = requestMethod.toUpperCase();
38
+ }
39
+ /**
40
+ * Feed data into the parser.
41
+ *
42
+ * Returns `true` when the response is fully parsed.
43
+ * After that, call `getResult()` to retrieve the parsed response,
44
+ * and `getRemainder()` for any trailing bytes.
45
+ */
46
+ feed(data) {
47
+ this.buffer = Buffer.concat([this.buffer, data]);
48
+ while (this.state !== ParserState.Complete) {
49
+ switch (this.state) {
50
+ case ParserState.StatusLine:
51
+ if (!this.parseStatusLine())
52
+ return false;
53
+ break;
54
+ case ParserState.Headers:
55
+ if (!this.parseHeaders())
56
+ return false;
57
+ break;
58
+ case ParserState.Body:
59
+ if (!this.parseBody())
60
+ return false;
61
+ break;
62
+ case ParserState.ChunkedBody:
63
+ if (!this.parseChunkedBody())
64
+ return false;
65
+ break;
66
+ }
67
+ }
68
+ return true;
69
+ }
70
+ getResult() {
71
+ if (!this.result) {
72
+ throw new Error('Response not fully parsed');
73
+ }
74
+ return this.result;
75
+ }
76
+ /** Get remaining data after the response (for connection reuse). */
77
+ getRemainder() {
78
+ return this.buffer;
79
+ }
80
+ parseStatusLine() {
81
+ const idx = this.buffer.indexOf('\r\n');
82
+ if (idx === -1) {
83
+ if (this.buffer.length > HttpResponseParser.MAX_HEADER_SIZE) {
84
+ throw new Error('Status line too long');
85
+ }
86
+ return false;
87
+ }
88
+ const line = this.buffer.subarray(0, idx).toString('latin1');
89
+ this.buffer = this.buffer.subarray(idx + 2);
90
+ const match = /^(HTTP\/\d\.\d)\s+(\d{3})\s*(.*)$/.exec(line);
91
+ if (!match) {
92
+ throw new Error(`Invalid HTTP status line: ${line.substring(0, 100)}`);
93
+ }
94
+ this.httpVersion = match[1];
95
+ this.statusCode = parseInt(match[2], 10);
96
+ this.statusMessage = match[3] ?? '';
97
+ this.state = ParserState.Headers;
98
+ return true;
99
+ }
100
+ parseHeaders() {
101
+ while (true) {
102
+ const idx = this.buffer.indexOf('\r\n');
103
+ if (idx === -1) {
104
+ if (this.buffer.length > HttpResponseParser.MAX_HEADER_SIZE) {
105
+ throw new Error('Header section too large');
106
+ }
107
+ return false;
108
+ }
109
+ const line = this.buffer.subarray(0, idx).toString('latin1');
110
+ this.buffer = this.buffer.subarray(idx + 2);
111
+ if (line === '') {
112
+ // End of headers
113
+ this.finalizeHeaders();
114
+ return true;
115
+ }
116
+ const colonIdx = line.indexOf(':');
117
+ if (colonIdx === -1) {
118
+ throw new Error(`Invalid header line: ${line.substring(0, 100)}`);
119
+ }
120
+ const name = line.substring(0, colonIdx);
121
+ const value = line.substring(colonIdx + 1).trim();
122
+ this.rawHeaders.push([name, value]);
123
+ const lower = name.toLowerCase();
124
+ const existing = this.headers.get(lower);
125
+ if (existing !== undefined) {
126
+ this.headers.set(lower, existing + ', ' + value);
127
+ }
128
+ else {
129
+ this.headers.set(lower, value);
130
+ }
131
+ }
132
+ }
133
+ finalizeHeaders() {
134
+ // HEAD responses never have a body (RFC 9110 §9.3.2)
135
+ if (this.requestMethod === 'HEAD') {
136
+ this.finalize();
137
+ return;
138
+ }
139
+ // Determine body framing
140
+ const te = this.headers.get('transfer-encoding');
141
+ if (te && te.toLowerCase().includes('chunked')) {
142
+ this.isChunked = true;
143
+ this.state = ParserState.ChunkedBody;
144
+ return;
145
+ }
146
+ const cl = this.headers.get('content-length');
147
+ if (cl !== undefined) {
148
+ this.contentLength = parseInt(cl, 10);
149
+ if (Number.isNaN(this.contentLength) || this.contentLength < 0) {
150
+ throw new Error(`Invalid content-length: ${cl}`);
151
+ }
152
+ if (this.contentLength === 0) {
153
+ this.finalize();
154
+ return;
155
+ }
156
+ this.state = ParserState.Body;
157
+ return;
158
+ }
159
+ // No content-length, no chunked -- could be:
160
+ // 1xx, 204, 304 → no body
161
+ // Everything else → read until connection close
162
+ if (this.statusCode === 204 ||
163
+ this.statusCode === 304 ||
164
+ (this.statusCode >= 100 && this.statusCode < 200)) {
165
+ this.finalize();
166
+ return;
167
+ }
168
+ // Read until close -- set contentLength to a sentinel
169
+ this.contentLength = -1;
170
+ this.state = ParserState.Body;
171
+ }
172
+ parseBody() {
173
+ if (this.contentLength >= 0) {
174
+ const needed = this.contentLength - this.bodyBytesRead;
175
+ if (this.buffer.length >= needed) {
176
+ this.bodyChunks.push(this.buffer.subarray(0, needed));
177
+ this.bodyBytesRead += needed;
178
+ this.buffer = this.buffer.subarray(needed);
179
+ this.finalize();
180
+ return true;
181
+ }
182
+ // Not enough data yet
183
+ this.bodyChunks.push(Buffer.from(this.buffer));
184
+ this.bodyBytesRead += this.buffer.length;
185
+ this.buffer = Buffer.alloc(0);
186
+ return false;
187
+ }
188
+ // Read until close -- accumulate everything
189
+ if (this.buffer.length > 0) {
190
+ this.bodyChunks.push(Buffer.from(this.buffer));
191
+ this.bodyBytesRead += this.buffer.length;
192
+ if (this.bodyBytesRead > HttpResponseParser.MAX_BODY_SIZE) {
193
+ throw new Error('Response body exceeds maximum size');
194
+ }
195
+ this.buffer = Buffer.alloc(0);
196
+ }
197
+ return false;
198
+ }
199
+ parseChunkedBody() {
200
+ while (true) {
201
+ // Read chunk size line
202
+ const idx = this.buffer.indexOf('\r\n');
203
+ if (idx === -1)
204
+ return false;
205
+ const sizeLine = this.buffer.subarray(0, idx).toString('latin1').trim();
206
+ // Chunk extensions are ignored (per spec)
207
+ const semiIdx = sizeLine.indexOf(';');
208
+ const sizeStr = semiIdx >= 0 ? sizeLine.substring(0, semiIdx) : sizeLine;
209
+ const chunkSize = parseInt(sizeStr, 16);
210
+ if (Number.isNaN(chunkSize)) {
211
+ throw new Error(`Invalid chunk size: ${sizeLine.substring(0, 20)}`);
212
+ }
213
+ // Need: chunk-size-line + \r\n + chunk-data + \r\n
214
+ const totalNeeded = idx + 2 + chunkSize + 2;
215
+ if (this.buffer.length < totalNeeded)
216
+ return false;
217
+ if (chunkSize === 0) {
218
+ // Terminal chunk
219
+ this.buffer = this.buffer.subarray(totalNeeded);
220
+ // Skip optional trailers
221
+ const trailerEnd = this.buffer.indexOf('\r\n');
222
+ if (trailerEnd >= 0) {
223
+ this.buffer = this.buffer.subarray(trailerEnd + 2);
224
+ }
225
+ this.finalize();
226
+ return true;
227
+ }
228
+ const chunkData = this.buffer.subarray(idx + 2, idx + 2 + chunkSize);
229
+ this.bodyChunks.push(Buffer.from(chunkData));
230
+ this.bodyBytesRead += chunkSize;
231
+ if (this.bodyBytesRead > HttpResponseParser.MAX_BODY_SIZE) {
232
+ throw new Error('Response body exceeds maximum size');
233
+ }
234
+ this.buffer = this.buffer.subarray(totalNeeded);
235
+ }
236
+ }
237
+ finalize() {
238
+ this.state = ParserState.Complete;
239
+ this.result = {
240
+ httpVersion: this.httpVersion,
241
+ statusCode: this.statusCode,
242
+ statusMessage: this.statusMessage,
243
+ headers: this.headers,
244
+ rawHeaders: this.rawHeaders,
245
+ body: Buffer.concat(this.bodyChunks),
246
+ };
247
+ }
248
+ /**
249
+ * Signal that the connection was closed.
250
+ * Finalizes a "read until close" body.
251
+ */
252
+ connectionClosed() {
253
+ if (this.state === ParserState.Body && this.contentLength === -1) {
254
+ this.finalize();
255
+ }
256
+ }
257
+ }
258
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../../../src/http/h1/parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH,IAAK,WAMJ;AAND,WAAK,WAAW;IACd,yDAAU,CAAA;IACV,mDAAO,CAAA;IACP,6CAAI,CAAA;IACJ,2DAAW,CAAA;IACX,qDAAQ,CAAA;AACV,CAAC,EANI,WAAW,KAAX,WAAW,QAMf;AAED;;GAEG;AACH,MAAM,OAAO,kBAAkB;IACrB,aAAa,CAAS;IACtB,KAAK,GAAG,WAAW,CAAC,UAAU,CAAC;IAC/B,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACzB,WAAW,GAAG,EAAE,CAAC;IACjB,UAAU,GAAG,CAAC,CAAC;IACf,aAAa,GAAG,EAAE,CAAC;IACnB,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;IACpC,UAAU,GAA4B,EAAE,CAAC;IACzC,aAAa,GAAG,CAAC,CAAC,CAAC;IACnB,SAAS,GAAG,KAAK,CAAC;IAClB,UAAU,GAAa,EAAE,CAAC;IAC1B,aAAa,GAAG,CAAC,CAAC;IAClB,MAAM,GAA0B,IAAI,CAAC;IAE7C,4CAA4C;IACpC,MAAM,CAAU,eAAe,GAAG,MAAM,CAAC;IACjD,kCAAkC;IAC1B,MAAM,CAAU,aAAa,GAAG,SAAS,CAAC;IAElD,YAAY,aAAa,GAAG,KAAK;QAC/B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC,WAAW,EAAE,CAAC;IACnD,CAAC;IAED;;;;;;OAMG;IACH,IAAI,CAAC,IAAY;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;QAEjD,OAAO,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC,QAAQ,EAAE,CAAC;YAC3C,QAAQ,IAAI,CAAC,KAAK,EAAE,CAAC;gBACnB,KAAK,WAAW,CAAC,UAAU;oBACzB,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE;wBAAE,OAAO,KAAK,CAAC;oBAC1C,MAAM;gBACR,KAAK,WAAW,CAAC,OAAO;oBACtB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE;wBAAE,OAAO,KAAK,CAAC;oBACvC,MAAM;gBACR,KAAK,WAAW,CAAC,IAAI;oBACnB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;wBAAE,OAAO,KAAK,CAAC;oBACpC,MAAM;gBACR,KAAK,WAAW,CAAC,WAAW;oBAC1B,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;wBAAE,OAAO,KAAK,CAAC;oBAC3C,MAAM;YACV,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,SAAS;QACP,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,oEAAoE;IACpE,YAAY;QACV,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAEO,eAAe;QACrB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;YACf,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,kBAAkB,CAAC,eAAe,EAAE,CAAC;gBAC5D,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;YAC1C,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC7D,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;QAE5C,MAAM,KAAK,GAAG,mCAAmC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACzE,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,YAAY;QAClB,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACxC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;gBACf,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,kBAAkB,CAAC,eAAe,EAAE,CAAC;oBAC5D,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;gBAC9C,CAAC;gBACD,OAAO,KAAK,CAAC;YACf,CAAC;YAED,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC7D,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;YAE5C,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;gBAChB,iBAAiB;gBACjB,IAAI,CAAC,eAAe,EAAE,CAAC;gBACvB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;gBACpB,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YACpE,CAAC;YAED,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;YACzC,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAClD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;YAEpC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACzC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,GAAG,KAAK,CAAC,CAAC;YACnD,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IAEO,eAAe;QACrB,qDAAqD;QACrD,IAAI,IAAI,CAAC,aAAa,KAAK,MAAM,EAAE,CAAC;YAClC,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QAED,yBAAyB;QACzB,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACjD,IAAI,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/C,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,WAAW,CAAC;YACrC,OAAO;QACT,CAAC;QAED,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;QAC9C,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACrB,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACtC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;gBAC/D,MAAM,IAAI,KAAK,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC;YACnD,CAAC;YACD,IAAI,IAAI,CAAC,aAAa,KAAK,CAAC,EAAE,CAAC;gBAC7B,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAChB,OAAO;YACT,CAAC;YACD,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,6CAA6C;QAC7C,4BAA4B;QAC5B,kDAAkD;QAClD,IACE,IAAI,CAAC,UAAU,KAAK,GAAG;YACvB,IAAI,CAAC,UAAU,KAAK,GAAG;YACvB,CAAC,IAAI,CAAC,UAAU,IAAI,GAAG,IAAI,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,EACjD,CAAC;YACD,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QAED,sDAAsD;QACtD,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC;IAChC,CAAC;IAEO,SAAS;QACf,IAAI,IAAI,CAAC,aAAa,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;YACvD,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC;gBACjC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;gBACtD,IAAI,CAAC,aAAa,IAAI,MAAM,CAAC;gBAC7B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAC3C,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAChB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,sBAAsB;YACtB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YAC/C,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YACzC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC9B,OAAO,KAAK,CAAC;QACf,CAAC;QAED,4CAA4C;QAC5C,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YAC/C,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YACzC,IAAI,IAAI,CAAC,aAAa,GAAG,kBAAkB,CAAC,aAAa,EAAE,CAAC;gBAC1D,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACxD,CAAC;YACD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,gBAAgB;QACtB,OAAO,IAAI,EAAE,CAAC;YACZ,uBAAuB;YACvB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACxC,IAAI,GAAG,KAAK,CAAC,CAAC;gBAAE,OAAO,KAAK,CAAC;YAE7B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;YACxE,0CAA0C;YAC1C,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACtC,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;YACzE,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAExC,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,uBAAuB,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;YACtE,CAAC;YAED,mDAAmD;YACnD,MAAM,WAAW,GAAG,GAAG,GAAG,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC;YAC5C,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,WAAW;gBAAE,OAAO,KAAK,CAAC;YAEnD,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;gBACpB,iBAAiB;gBACjB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;gBAChD,yBAAyB;gBACzB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC/C,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;oBACpB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;gBACrD,CAAC;gBACD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAChB,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC;YACrE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;YAC7C,IAAI,CAAC,aAAa,IAAI,SAAS,CAAC;YAEhC,IAAI,IAAI,CAAC,aAAa,GAAG,kBAAkB,CAAC,aAAa,EAAE,CAAC;gBAC1D,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACxD,CAAC;YAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAEO,QAAQ;QACd,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG;YACZ,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;SACrC,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,gBAAgB;QACd,IAAI,IAAI,CAAC,KAAK,KAAK,WAAW,CAAC,IAAI,IAAI,IAAI,CAAC,aAAa,KAAK,CAAC,CAAC,EAAE,CAAC;YACjE,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,CAAC;IACH,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * HTTP/2 client.
3
+ *
4
+ * Multiplexed HTTP/2 client that runs over a TLS Duplex stream.
5
+ * Sends the connection preface with browser-profile-matched SETTINGS
6
+ * and WINDOW_UPDATE for Akamai HTTP/2 fingerprint control.
7
+ */
8
+ import type { Duplex } from 'node:stream';
9
+ import type { NLcURLRequest, RequestTimings } from '../../core/request.js';
10
+ import { NLcURLResponse } from '../../core/response.js';
11
+ import type { H2Profile } from '../../fingerprints/types.js';
12
+ export declare class H2Client {
13
+ private readonly stream;
14
+ private readonly encoder;
15
+ private readonly decoder;
16
+ private readonly h2Profile;
17
+ private readonly defaultHeaders;
18
+ private nextStreamId;
19
+ private streams;
20
+ private readBuffer;
21
+ private prefaceSent;
22
+ private closed;
23
+ constructor(stream: Duplex, h2Profile?: H2Profile, defaultHeaders?: Array<[string, string]>);
24
+ /**
25
+ * Send the HTTP/2 connection preface.
26
+ *
27
+ * Must be called before sending any requests.
28
+ */
29
+ sendPreface(): void;
30
+ /**
31
+ * Send an HTTP/2 request and return the response.
32
+ */
33
+ request(req: NLcURLRequest, timings?: Partial<RequestTimings>): Promise<NLcURLResponse>;
34
+ /**
35
+ * Gracefully close the HTTP/2 connection.
36
+ */
37
+ close(): void;
38
+ destroy(): void;
39
+ private buildRequestHeaders;
40
+ private write;
41
+ private onData;
42
+ private processFrames;
43
+ private handleFrame;
44
+ private finalizeStream;
45
+ private onError;
46
+ private onClose;
47
+ }
48
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/http/h2/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAGxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAmC7D,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAClD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0B;IAEzD,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,UAAU,CAAmB;IACrC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAS;gBAGrB,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,SAAS,EACrB,cAAc,GAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM;IAa9C;;;;OAIG;IACH,WAAW,IAAI,IAAI;IA4CnB;;OAEG;IACG,OAAO,CACX,GAAG,EAAE,aAAa,EAClB,OAAO,GAAE,OAAO,CAAC,cAAc,CAAM,GACpC,OAAO,CAAC,cAAc,CAAC;IA8D1B;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb,OAAO,IAAI,IAAI;IAYf,OAAO,CAAC,mBAAmB;IAsD3B,OAAO,CAAC,KAAK;IAMb,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,WAAW;YAiFL,cAAc;IA8C5B,OAAO,CAAC,OAAO;IASf,OAAO,CAAC,OAAO;CAQhB"}