undici 5.28.0 → 5.28.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/lib/client.js CHANGED
@@ -917,11 +917,9 @@ class Parser {
917
917
  socket[kReset] = true
918
918
  }
919
919
 
920
- let pause
921
- try {
922
- pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false
923
- } catch (err) {
924
- util.destroy(socket, err)
920
+ const pause = request.onHeaders(statusCode, headers, this.resume, statusText) === false
921
+
922
+ if (request.aborted) {
925
923
  return -1
926
924
  }
927
925
 
@@ -968,13 +966,8 @@ class Parser {
968
966
 
969
967
  this.bytesRead += buf.length
970
968
 
971
- try {
972
- if (request.onData(buf) === false) {
973
- return constants.ERROR.PAUSED
974
- }
975
- } catch (err) {
976
- util.destroy(socket, err)
977
- return -1
969
+ if (request.onData(buf) === false) {
970
+ return constants.ERROR.PAUSED
978
971
  }
979
972
  }
980
973
 
@@ -1015,11 +1008,7 @@ class Parser {
1015
1008
  return -1
1016
1009
  }
1017
1010
 
1018
- try {
1019
- request.onComplete(headers)
1020
- } catch (err) {
1021
- errorRequest(client, request, err)
1022
- }
1011
+ request.onComplete(headers)
1023
1012
 
1024
1013
  client[kQueue][client[kRunningIdx]++] = null
1025
1014
 
@@ -1805,13 +1794,17 @@ function writeH2 (client, session, request) {
1805
1794
  })
1806
1795
 
1807
1796
  stream.on('data', (chunk) => {
1808
- if (request.onData(chunk) === false) stream.pause()
1797
+ if (request.onData(chunk) === false) {
1798
+ stream.pause()
1799
+ }
1809
1800
  })
1810
1801
 
1811
1802
  stream.once('close', () => {
1812
1803
  h2State.openStreams -= 1
1813
1804
  // TODO(HTTP/2): unref only if current streams count is 0
1814
- if (h2State.openStreams === 0) session.unref()
1805
+ if (h2State.openStreams === 0) {
1806
+ session.unref()
1807
+ }
1815
1808
  })
1816
1809
 
1817
1810
  stream.once('error', function (err) {
@@ -229,7 +229,11 @@ class Request {
229
229
 
230
230
  onBodySent (chunk) {
231
231
  if (this[kHandler].onBodySent) {
232
- return this[kHandler].onBodySent(chunk)
232
+ try {
233
+ return this[kHandler].onBodySent(chunk)
234
+ } catch (err) {
235
+ this.abort(err)
236
+ }
233
237
  }
234
238
  }
235
239
 
@@ -239,7 +243,11 @@ class Request {
239
243
  }
240
244
 
241
245
  if (this[kHandler].onRequestSent) {
242
- return this[kHandler].onRequestSent()
246
+ try {
247
+ return this[kHandler].onRequestSent()
248
+ } catch (err) {
249
+ this.abort(err)
250
+ }
243
251
  }
244
252
  }
245
253
 
@@ -263,14 +271,23 @@ class Request {
263
271
  channels.headers.publish({ request: this, response: { statusCode, headers, statusText } })
264
272
  }
265
273
 
266
- return this[kHandler].onHeaders(statusCode, headers, resume, statusText)
274
+ try {
275
+ return this[kHandler].onHeaders(statusCode, headers, resume, statusText)
276
+ } catch (err) {
277
+ this.abort(err)
278
+ }
267
279
  }
268
280
 
269
281
  onData (chunk) {
270
282
  assert(!this.aborted)
271
283
  assert(!this.completed)
272
284
 
273
- return this[kHandler].onData(chunk)
285
+ try {
286
+ return this[kHandler].onData(chunk)
287
+ } catch (err) {
288
+ this.abort(err)
289
+ return false
290
+ }
274
291
  }
275
292
 
276
293
  onUpgrade (statusCode, headers, socket) {
@@ -289,7 +306,13 @@ class Request {
289
306
  if (channels.trailers.hasSubscribers) {
290
307
  channels.trailers.publish({ request: this, trailers })
291
308
  }
292
- return this[kHandler].onComplete(trailers)
309
+
310
+ try {
311
+ return this[kHandler].onComplete(trailers)
312
+ } catch (err) {
313
+ // TODO (fix): This might be a bad idea?
314
+ this.onError(err)
315
+ }
293
316
  }
294
317
 
295
318
  onError (error) {
@@ -303,6 +326,7 @@ class Request {
303
326
  return
304
327
  }
305
328
  this.aborted = true
329
+
306
330
  return this[kHandler].onError(error)
307
331
  }
308
332
 
@@ -10,7 +10,8 @@ const {
10
10
  isValidHTTPToken,
11
11
  sameOrigin,
12
12
  normalizeMethod,
13
- makePolicyContainer
13
+ makePolicyContainer,
14
+ normalizeMethodRecord
14
15
  } = require('./util')
15
16
  const {
16
17
  forbiddenMethodsSet,
@@ -183,8 +184,10 @@ class Request {
183
184
  urlList: [...request.urlList]
184
185
  })
185
186
 
187
+ const initHasKey = Object.keys(init).length !== 0
188
+
186
189
  // 13. If init is not empty, then:
187
- if (Object.keys(init).length > 0) {
190
+ if (initHasKey) {
188
191
  // 1. If request’s mode is "navigate", then set it to "same-origin".
189
192
  if (request.mode === 'navigate') {
190
193
  request.mode = 'same-origin'
@@ -315,16 +318,16 @@ class Request {
315
318
 
316
319
  // 2. If method is not a method or method is a forbidden method, then
317
320
  // throw a TypeError.
318
- if (!isValidHTTPToken(init.method)) {
319
- throw new TypeError(`'${init.method}' is not a valid HTTP method.`)
321
+ if (!isValidHTTPToken(method)) {
322
+ throw new TypeError(`'${method}' is not a valid HTTP method.`)
320
323
  }
321
324
 
322
325
  if (forbiddenMethodsSet.has(method.toUpperCase())) {
323
- throw new TypeError(`'${init.method}' HTTP method is unsupported.`)
326
+ throw new TypeError(`'${method}' HTTP method is unsupported.`)
324
327
  }
325
328
 
326
329
  // 3. Normalize method.
327
- method = normalizeMethod(init.method)
330
+ method = normalizeMethodRecord[method] ?? normalizeMethod(method)
328
331
 
329
332
  // 4. Set request’s method to method.
330
333
  request.method = method
@@ -415,25 +418,25 @@ class Request {
415
418
  }
416
419
 
417
420
  // 32. If init is not empty, then:
418
- if (Object.keys(init).length !== 0) {
421
+ if (initHasKey) {
422
+ /** @type {HeadersList} */
423
+ const headersList = this[kHeaders][kHeadersList]
419
424
  // 1. Let headers be a copy of this’s headers and its associated header
420
425
  // list.
421
- let headers = new Headers(this[kHeaders])
422
-
423
426
  // 2. If init["headers"] exists, then set headers to init["headers"].
424
- if (init.headers !== undefined) {
425
- headers = init.headers
426
- }
427
+ const headers = init.headers !== undefined ? init.headers : new HeadersList(headersList)
427
428
 
428
429
  // 3. Empty this’s headers’s header list.
429
- this[kHeaders][kHeadersList].clear()
430
+ headersList.clear()
430
431
 
431
432
  // 4. If headers is a Headers object, then for each header in its header
432
433
  // list, append header’s name/header’s value to this’s headers.
433
- if (headers.constructor.name === 'Headers') {
434
+ if (headers instanceof HeadersList) {
434
435
  for (const [key, val] of headers) {
435
- this[kHeaders].append(key, val)
436
+ headersList.append(key, val)
436
437
  }
438
+ // Note: Copy the `set-cookie` meta-data.
439
+ headersList.cookies = headers.cookies
437
440
  } else {
438
441
  // 5. Otherwise, fill this’s headers with headers.
439
442
  fillHeaders(this[kHeaders], headers)
package/lib/fetch/util.js CHANGED
@@ -698,11 +698,30 @@ function isCancelled (fetchParams) {
698
698
  fetchParams.controller.state === 'terminated'
699
699
  }
700
700
 
701
- // https://fetch.spec.whatwg.org/#concept-method-normalize
701
+ const normalizeMethodRecord = {
702
+ delete: 'DELETE',
703
+ DELETE: 'DELETE',
704
+ get: 'GET',
705
+ GET: 'GET',
706
+ head: 'HEAD',
707
+ HEAD: 'HEAD',
708
+ options: 'OPTIONS',
709
+ OPTIONS: 'OPTIONS',
710
+ post: 'POST',
711
+ POST: 'POST',
712
+ put: 'PUT',
713
+ PUT: 'PUT'
714
+ }
715
+
716
+ // Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`.
717
+ Object.setPrototypeOf(normalizeMethodRecord, null)
718
+
719
+ /**
720
+ * @see https://fetch.spec.whatwg.org/#concept-method-normalize
721
+ * @param {string} method
722
+ */
702
723
  function normalizeMethod (method) {
703
- return /^(DELETE|GET|HEAD|OPTIONS|POST|PUT)$/i.test(method)
704
- ? method.toUpperCase()
705
- : method
724
+ return normalizeMethodRecord[method.toLowerCase()] ?? method
706
725
  }
707
726
 
708
727
  // https://infra.spec.whatwg.org/#serialize-a-javascript-value-to-a-json-string
@@ -1047,5 +1066,6 @@ module.exports = {
1047
1066
  urlIsLocal,
1048
1067
  urlHasHttpsScheme,
1049
1068
  urlIsHttpHttpsScheme,
1050
- readAllBytes
1069
+ readAllBytes,
1070
+ normalizeMethodRecord
1051
1071
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "undici",
3
- "version": "5.28.0",
3
+ "version": "5.28.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": {