undici 5.27.0 → 5.27.2

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/lib/client.js CHANGED
@@ -1462,23 +1462,7 @@ function _resume (client, sync) {
1462
1462
  return
1463
1463
  }
1464
1464
 
1465
- if (util.isStream(request.body) && util.bodyLength(request.body) === 0) {
1466
- request.body
1467
- .on('data', /* istanbul ignore next */ function () {
1468
- /* istanbul ignore next */
1469
- assert(false)
1470
- })
1471
- .on('error', function (err) {
1472
- errorRequest(client, request, err)
1473
- })
1474
- .on('end', function () {
1475
- util.destroy(this)
1476
- })
1477
-
1478
- request.body = null
1479
- }
1480
-
1481
- if (client[kRunning] > 0 &&
1465
+ if (client[kRunning] > 0 && util.bodyLength(request.body) !== 0 &&
1482
1466
  (util.isStream(request.body) || util.isAsyncIterable(request.body))) {
1483
1467
  // Request with stream or iterator body can error while other requests
1484
1468
  // are inflight and indirectly error those as well.
@@ -1499,6 +1483,11 @@ function _resume (client, sync) {
1499
1483
  }
1500
1484
  }
1501
1485
 
1486
+ // https://www.rfc-editor.org/rfc/rfc7230#section-3.3.2
1487
+ function shouldSendContentLength (method) {
1488
+ return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT'
1489
+ }
1490
+
1502
1491
  function write (client, request) {
1503
1492
  if (client[kHTTPConnVersion] === 'h2') {
1504
1493
  writeH2(client, client[kHTTP2Session], request)
@@ -1527,7 +1516,9 @@ function write (client, request) {
1527
1516
  body.read(0)
1528
1517
  }
1529
1518
 
1530
- let contentLength = util.bodyLength(body)
1519
+ const bodyLength = util.bodyLength(body)
1520
+
1521
+ let contentLength = bodyLength
1531
1522
 
1532
1523
  if (contentLength === null) {
1533
1524
  contentLength = request.contentLength
@@ -1542,7 +1533,9 @@ function write (client, request) {
1542
1533
  contentLength = null
1543
1534
  }
1544
1535
 
1545
- if (request.contentLength !== null && request.contentLength !== contentLength) {
1536
+ // https://github.com/nodejs/undici/issues/2046
1537
+ // A user agent may send a Content-Length header with 0 value, this should be allowed.
1538
+ if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength !== null && request.contentLength !== contentLength) {
1546
1539
  if (client[kStrictContentLength]) {
1547
1540
  errorRequest(client, request, new RequestContentLengthMismatchError())
1548
1541
  return false
@@ -1623,7 +1616,7 @@ function write (client, request) {
1623
1616
  }
1624
1617
 
1625
1618
  /* istanbul ignore else: assertion */
1626
- if (!body) {
1619
+ if (!body || bodyLength === 0) {
1627
1620
  if (contentLength === 0) {
1628
1621
  socket.write(`${header}content-length: 0\r\n\r\n`, 'latin1')
1629
1622
  } else {
@@ -1763,7 +1756,9 @@ function writeH2 (client, session, request) {
1763
1756
  contentLength = null
1764
1757
  }
1765
1758
 
1766
- if (request.contentLength != null && request.contentLength !== contentLength) {
1759
+ // https://github.com/nodejs/undici/issues/2046
1760
+ // A user agent may send a Content-Length header with 0 value, this should be allowed.
1761
+ if (shouldSendContentLength(method) && contentLength > 0 && request.contentLength != null && request.contentLength !== contentLength) {
1767
1762
  if (client[kStrictContentLength]) {
1768
1763
  errorRequest(client, request, new RequestContentLengthMismatchError())
1769
1764
  return false
@@ -112,10 +112,29 @@ class Request {
112
112
 
113
113
  this.method = method
114
114
 
115
+ this.abort = null
116
+
115
117
  if (body == null) {
116
118
  this.body = null
117
119
  } else if (util.isStream(body)) {
118
120
  this.body = body
121
+
122
+ const rState = this.body._readableState
123
+ if (!rState || !rState.autoDestroy) {
124
+ this.endHandler = function autoDestroy () {
125
+ util.destroy(this)
126
+ }
127
+ this.body.on('end', this.endHandler)
128
+ }
129
+
130
+ this.errorHandler = err => {
131
+ if (this.abort) {
132
+ this.abort(err)
133
+ } else {
134
+ this.error = err
135
+ }
136
+ }
137
+ this.body.on('error', this.errorHandler)
119
138
  } else if (util.isBuffer(body)) {
120
139
  this.body = body.byteLength ? body : null
121
140
  } else if (ArrayBuffer.isView(body)) {
@@ -236,7 +255,12 @@ class Request {
236
255
  assert(!this.aborted)
237
256
  assert(!this.completed)
238
257
 
239
- return this[kHandler].onConnect(abort)
258
+ if (this.error) {
259
+ abort(this.error)
260
+ } else {
261
+ this.abort = abort
262
+ return this[kHandler].onConnect(abort)
263
+ }
240
264
  }
241
265
 
242
266
  onHeaders (statusCode, headers, resume, statusText) {
@@ -265,6 +289,8 @@ class Request {
265
289
  }
266
290
 
267
291
  onComplete (trailers) {
292
+ this.onFinally()
293
+
268
294
  assert(!this.aborted)
269
295
 
270
296
  this.completed = true
@@ -275,6 +301,8 @@ class Request {
275
301
  }
276
302
 
277
303
  onError (error) {
304
+ this.onFinally()
305
+
278
306
  if (channels.error.hasSubscribers) {
279
307
  channels.error.publish({ request: this, error })
280
308
  }
@@ -286,6 +314,18 @@ class Request {
286
314
  return this[kHandler].onError(error)
287
315
  }
288
316
 
317
+ onFinally () {
318
+ if (this.errorHandler) {
319
+ this.body.off('error', this.errorHandler)
320
+ this.errorHandler = null
321
+ }
322
+
323
+ if (this.endHandler) {
324
+ this.body.off('end', this.endHandler)
325
+ this.endHandler = null
326
+ }
327
+ }
328
+
289
329
  // TODO: adjust to support H2
290
330
  addHeader (key, value) {
291
331
  processHeader(this, key, value)
package/lib/core/util.js CHANGED
@@ -190,7 +190,7 @@ function isReadableAborted (stream) {
190
190
  }
191
191
 
192
192
  function destroy (stream, err) {
193
- if (!isStream(stream) || isDestroyed(stream)) {
193
+ if (stream == null || !isStream(stream) || isDestroyed(stream)) {
194
194
  return
195
195
  }
196
196
 
package/lib/pool.js CHANGED
@@ -57,7 +57,7 @@ class Pool extends PoolBase {
57
57
  maxCachedSessions,
58
58
  allowH2,
59
59
  socketPath,
60
- timeout: connectTimeout == null ? 10e3 : connectTimeout,
60
+ timeout: connectTimeout,
61
61
  ...(util.nodeHasAutoSelectFamily && autoSelectFamily ? { autoSelectFamily, autoSelectFamilyAttemptTimeout } : undefined),
62
62
  ...connect
63
63
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "undici",
3
- "version": "5.27.0",
3
+ "version": "5.27.2",
4
4
  "description": "An HTTP/1.1 client, written from scratch for Node.js",
5
5
  "homepage": "https://undici.nodejs.org",
6
6
  "bugs": {