undici 7.1.0 → 7.1.1
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 +25 -9
- package/docs/docs/api/ProxyAgent.md +10 -2
- package/index.js +2 -9
- package/lib/cache/sqlite-cache-store.js +5 -1
- package/lib/dispatcher/client-h2.js +9 -0
- package/lib/handler/wrap-handler.js +3 -6
- package/lib/interceptor/cache.js +5 -2
- package/lib/interceptor/dns.js +1 -1
- package/lib/interceptor/response-error.js +3 -3
- package/lib/web/fetch/data-url.js +2 -2
- package/package.json +3 -3
- package/types/index.d.ts +2 -1
package/README.md
CHANGED
|
@@ -281,17 +281,23 @@ stalls or deadlocks when running out of connections.
|
|
|
281
281
|
|
|
282
282
|
```js
|
|
283
283
|
// Do
|
|
284
|
-
const headers = await fetch(url)
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
return res.headers
|
|
290
|
-
})
|
|
284
|
+
const { body, headers } = await fetch(url);
|
|
285
|
+
for await (const chunk of body) {
|
|
286
|
+
// force consumption of body
|
|
287
|
+
}
|
|
291
288
|
|
|
292
289
|
// Do not
|
|
293
|
-
const headers = await fetch(url)
|
|
294
|
-
|
|
290
|
+
const { headers } = await fetch(url);
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
The same applies for `request` too:
|
|
294
|
+
```js
|
|
295
|
+
// Do
|
|
296
|
+
const { body, headers } = await request(url);
|
|
297
|
+
await res.body.dump(); // force consumption of body
|
|
298
|
+
|
|
299
|
+
// Do not
|
|
300
|
+
const { headers } = await request(url);
|
|
295
301
|
```
|
|
296
302
|
|
|
297
303
|
However, if you want to get only headers, it might be better to use `HEAD` request method. Usage of this method will obviate the need for consumption or cancelling of the response body. See [MDN - HTTP - HTTP request methods - HEAD](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD) for more details.
|
|
@@ -445,6 +451,16 @@ and `undici.Agent`) which will enable the family autoselection algorithm when es
|
|
|
445
451
|
* [__Robert Nagy__](https://github.com/ronag), <https://www.npmjs.com/~ronag>
|
|
446
452
|
* [__Matthew Aitken__](https://github.com/KhafraDev), <https://www.npmjs.com/~khaf>
|
|
447
453
|
|
|
454
|
+
## Long Term Support
|
|
455
|
+
|
|
456
|
+
Undici aligns with the Node.js LTS schedule. The following table shows the supported versions:
|
|
457
|
+
|
|
458
|
+
| Version | Node.js | End of Life |
|
|
459
|
+
|---------|-------------|-------------|
|
|
460
|
+
| 5.x | v18.x | 2024-04-30 |
|
|
461
|
+
| 6.x | v20.x v22.x | 2026-04-30 |
|
|
462
|
+
| 7.x | v24.x | 2027-04-30 |
|
|
463
|
+
|
|
448
464
|
## License
|
|
449
465
|
|
|
450
466
|
MIT
|
|
@@ -15,6 +15,7 @@ Returns: `ProxyAgent`
|
|
|
15
15
|
### Parameter: `ProxyAgentOptions`
|
|
16
16
|
|
|
17
17
|
Extends: [`AgentOptions`](/docs/docs/api/Agent.md#parameter-agentoptions)
|
|
18
|
+
> It ommits `AgentOptions#connect`.
|
|
18
19
|
|
|
19
20
|
* **uri** `string | URL` (required) - The URI of the proxy server. This can be provided as a string, as an instance of the URL class, or as an object with a `uri` property of type string.
|
|
20
21
|
If the `uri` is provided as a string or `uri` is an object with an `uri` property of type string, then it will be parsed into a `URL` object according to the [WHATWG URL Specification](https://url.spec.whatwg.org).
|
|
@@ -22,8 +23,8 @@ For detailed information on the parsing process and potential validation errors,
|
|
|
22
23
|
* **token** `string` (optional) - It can be passed by a string of token for authentication.
|
|
23
24
|
* **auth** `string` (**deprecated**) - Use token.
|
|
24
25
|
* **clientFactory** `(origin: URL, opts: Object) => Dispatcher` (optional) - Default: `(origin, opts) => new Pool(origin, opts)`
|
|
25
|
-
* **requestTls** `BuildOptions` (optional) - Options object passed when creating the underlying socket via the connector builder for the request.
|
|
26
|
-
* **proxyTls** `BuildOptions` (optional) - Options object passed when creating the underlying socket via the connector builder for the proxy server.
|
|
26
|
+
* **requestTls** `BuildOptions` (optional) - Options object passed when creating the underlying socket via the connector builder for the request. It extends from [`Client#ConnectOptions`](/docs/docs/api/Client.md#parameter-connectoptions).
|
|
27
|
+
* **proxyTls** `BuildOptions` (optional) - Options object passed when creating the underlying socket via the connector builder for the proxy server. It extends from [`Client#ConnectOptions`](/docs/docs/api/Client.md#parameter-connectoptions).
|
|
27
28
|
|
|
28
29
|
Examples:
|
|
29
30
|
|
|
@@ -35,6 +36,13 @@ const proxyAgent = new ProxyAgent('my.proxy.server')
|
|
|
35
36
|
const proxyAgent = new ProxyAgent(new URL('my.proxy.server'))
|
|
36
37
|
// or
|
|
37
38
|
const proxyAgent = new ProxyAgent({ uri: 'my.proxy.server' })
|
|
39
|
+
// or
|
|
40
|
+
const proxyAgent = new ProxyAgent({
|
|
41
|
+
uri: new URL('my.proxy.server'),
|
|
42
|
+
proxyTls: {
|
|
43
|
+
signal: AbortSignal.timeout(1000)
|
|
44
|
+
}
|
|
45
|
+
})
|
|
38
46
|
```
|
|
39
47
|
|
|
40
48
|
#### Example - Basic ProxyAgent instantiation
|
package/index.js
CHANGED
|
@@ -49,15 +49,8 @@ module.exports.cacheStores = {
|
|
|
49
49
|
MemoryCacheStore: require('./lib/cache/memory-cache-store')
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
module.exports.cacheStores.SqliteCacheStore = SqliteCacheStore
|
|
55
|
-
} catch (err) {
|
|
56
|
-
// Most likely node:sqlite was not present, since SqliteCacheStore is
|
|
57
|
-
// optional, don't throw. Don't check specific error codes here because while
|
|
58
|
-
// ERR_UNKNOWN_BUILTIN_MODULE is expected, users have seen other codes like
|
|
59
|
-
// MODULE_NOT_FOUND
|
|
60
|
-
}
|
|
52
|
+
const SqliteCacheStore = require('./lib/cache/sqlite-cache-store')
|
|
53
|
+
module.exports.cacheStores.SqliteCacheStore = SqliteCacheStore
|
|
61
54
|
|
|
62
55
|
module.exports.buildConnector = buildConnector
|
|
63
56
|
module.exports.errors = errors
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { DatabaseSync } = require('node:sqlite')
|
|
4
3
|
const { Writable } = require('stream')
|
|
5
4
|
const { assertCacheKey, assertCacheValue } = require('../util/cache.js')
|
|
6
5
|
|
|
6
|
+
let DatabaseSync
|
|
7
|
+
|
|
7
8
|
const VERSION = 3
|
|
8
9
|
|
|
9
10
|
// 2gb
|
|
@@ -101,6 +102,9 @@ module.exports = class SqliteCacheStore {
|
|
|
101
102
|
}
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
if (!DatabaseSync) {
|
|
106
|
+
DatabaseSync = require('node:sqlite').DatabaseSync
|
|
107
|
+
}
|
|
104
108
|
this.#db = new DatabaseSync(opts?.location ?? ':memory:')
|
|
105
109
|
|
|
106
110
|
this.#db.exec(`
|
|
@@ -30,6 +30,7 @@ const {
|
|
|
30
30
|
kClosed,
|
|
31
31
|
kBodyTimeout
|
|
32
32
|
} = require('../core/symbols.js')
|
|
33
|
+
const { channels } = require('../core/diagnostics.js')
|
|
33
34
|
|
|
34
35
|
const kOpenStreams = Symbol('open streams')
|
|
35
36
|
|
|
@@ -448,6 +449,14 @@ function writeH2 (client, request) {
|
|
|
448
449
|
|
|
449
450
|
session.ref()
|
|
450
451
|
|
|
452
|
+
if (channels.sendHeaders.hasSubscribers) {
|
|
453
|
+
let header = ''
|
|
454
|
+
for (const key in headers) {
|
|
455
|
+
header += `${key}: ${headers[key]}\r\n`
|
|
456
|
+
}
|
|
457
|
+
channels.sendHeaders.publish({ request, headers: header, socket: session[kSocket] })
|
|
458
|
+
}
|
|
459
|
+
|
|
451
460
|
// TODO(metcoder95): add support for sending trailers
|
|
452
461
|
const shouldEndStream = method === 'GET' || method === 'HEAD' || body === null
|
|
453
462
|
if (expectContinue) {
|
|
@@ -53,8 +53,7 @@ module.exports = class WrapHandler {
|
|
|
53
53
|
onRequestUpgrade (controller, statusCode, headers, socket) {
|
|
54
54
|
const rawHeaders = []
|
|
55
55
|
for (const [key, val] of Object.entries(headers)) {
|
|
56
|
-
|
|
57
|
-
rawHeaders.push(Buffer.from(key), Buffer.from(val))
|
|
56
|
+
rawHeaders.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val))
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
this.#handler.onUpgrade?.(statusCode, rawHeaders, socket)
|
|
@@ -63,8 +62,7 @@ module.exports = class WrapHandler {
|
|
|
63
62
|
onResponseStart (controller, statusCode, headers, statusMessage) {
|
|
64
63
|
const rawHeaders = []
|
|
65
64
|
for (const [key, val] of Object.entries(headers)) {
|
|
66
|
-
|
|
67
|
-
rawHeaders.push(Buffer.from(key), Buffer.from(val))
|
|
65
|
+
rawHeaders.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val))
|
|
68
66
|
}
|
|
69
67
|
|
|
70
68
|
if (this.#handler.onHeaders?.(statusCode, rawHeaders, () => controller.resume(), statusMessage) === false) {
|
|
@@ -81,8 +79,7 @@ module.exports = class WrapHandler {
|
|
|
81
79
|
onResponseEnd (controller, trailers) {
|
|
82
80
|
const rawTrailers = []
|
|
83
81
|
for (const [key, val] of Object.entries(trailers)) {
|
|
84
|
-
|
|
85
|
-
rawTrailers.push(Buffer.from(key), Buffer.from(val))
|
|
82
|
+
rawTrailers.push(Buffer.from(key), Array.isArray(val) ? val.map(v => Buffer.from(v)) : Buffer.from(val))
|
|
86
83
|
}
|
|
87
84
|
|
|
88
85
|
this.#handler.onComplete?.(rawTrailers)
|
package/lib/interceptor/cache.js
CHANGED
|
@@ -225,8 +225,11 @@ function handleResult (
|
|
|
225
225
|
|
|
226
226
|
let headers = {
|
|
227
227
|
...opts.headers,
|
|
228
|
-
'if-modified-since': new Date(result.cachedAt).toUTCString()
|
|
229
|
-
|
|
228
|
+
'if-modified-since': new Date(result.cachedAt).toUTCString()
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (result.etag) {
|
|
232
|
+
headers['if-none-match'] = result.etag
|
|
230
233
|
}
|
|
231
234
|
|
|
232
235
|
if (result.vary) {
|
package/lib/interceptor/dns.js
CHANGED
|
@@ -16,7 +16,7 @@ class ResponseErrorHandler extends DecoratorHandler {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
#checkContentType (contentType) {
|
|
19
|
-
return this.#contentType.indexOf(contentType) === 0
|
|
19
|
+
return (this.#contentType ?? '').indexOf(contentType) === 0
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
onRequestStart (controller, context) {
|
|
@@ -81,8 +81,8 @@ class ResponseErrorHandler extends DecoratorHandler {
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
onResponseError (err) {
|
|
85
|
-
super.onResponseError(err)
|
|
84
|
+
onResponseError (controller, err) {
|
|
85
|
+
super.onResponseError(controller, err)
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -283,7 +283,7 @@ function parseMIMEType (input) {
|
|
|
283
283
|
|
|
284
284
|
// 5. If position is past the end of input, then return
|
|
285
285
|
// failure
|
|
286
|
-
if (position.position
|
|
286
|
+
if (position.position >= input.length) {
|
|
287
287
|
return 'failure'
|
|
288
288
|
}
|
|
289
289
|
|
|
@@ -364,7 +364,7 @@ function parseMIMEType (input) {
|
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
// 6. If position is past the end of input, then break.
|
|
367
|
-
if (position.position
|
|
367
|
+
if (position.position >= input.length) {
|
|
368
368
|
break
|
|
369
369
|
}
|
|
370
370
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "undici",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.1",
|
|
4
4
|
"description": "An HTTP/1.1 client, written from scratch for Node.js",
|
|
5
5
|
"homepage": "https://undici.nodejs.org",
|
|
6
6
|
"bugs": {
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
"prepare": "husky && node ./scripts/platform-shell.js"
|
|
107
107
|
},
|
|
108
108
|
"devDependencies": {
|
|
109
|
-
"@fastify/busboy": "3.
|
|
109
|
+
"@fastify/busboy": "3.1.0",
|
|
110
110
|
"@matteo.collina/tspl": "^0.1.1",
|
|
111
111
|
"@sinonjs/fake-timers": "^12.0.0",
|
|
112
112
|
"@types/node": "^18.19.50",
|
|
@@ -121,7 +121,7 @@
|
|
|
121
121
|
"https-pem": "^3.0.0",
|
|
122
122
|
"husky": "^9.0.7",
|
|
123
123
|
"jest": "^29.0.2",
|
|
124
|
-
"neostandard": "^0.
|
|
124
|
+
"neostandard": "^0.12.0",
|
|
125
125
|
"node-forge": "^1.3.1",
|
|
126
126
|
"proxy": "^2.1.1",
|
|
127
127
|
"tsd": "^0.31.2",
|
package/types/index.d.ts
CHANGED
|
@@ -64,6 +64,7 @@ declare namespace Undici {
|
|
|
64
64
|
const caches: typeof import('./cache').caches
|
|
65
65
|
const interceptors: typeof import('./interceptors').default
|
|
66
66
|
const cacheStores: {
|
|
67
|
-
MemoryCacheStore: typeof import('./cache-interceptor').default.MemoryCacheStore
|
|
67
|
+
MemoryCacheStore: typeof import('./cache-interceptor').default.MemoryCacheStore,
|
|
68
|
+
SqliteCacheStore: typeof import('./cache-interceptor').default.SqliteCacheStore
|
|
68
69
|
}
|
|
69
70
|
}
|