undici 4.11.1 → 4.11.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/fetch/body.js +5 -1
- package/lib/fetch/index.js +72 -68
- package/lib/fetch/symbols.js +2 -1
- package/package.json +1 -1
package/lib/fetch/body.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const util = require('../core/util')
|
|
4
4
|
const { ReadableStreamFrom, toUSVString, isBlobLike } = require('./util')
|
|
5
5
|
const { FormData } = require('./formdata')
|
|
6
|
-
const { kState } = require('./symbols')
|
|
6
|
+
const { kState, kError } = require('./symbols')
|
|
7
7
|
const { Blob } = require('buffer')
|
|
8
8
|
const { kBodyUsed } = require('../core/symbols')
|
|
9
9
|
const assert = require('assert')
|
|
@@ -268,6 +268,10 @@ const methods = {
|
|
|
268
268
|
if (this[kState].body) {
|
|
269
269
|
const stream = this[kState].body.stream
|
|
270
270
|
|
|
271
|
+
if (stream[kError]) {
|
|
272
|
+
throw stream[kError]
|
|
273
|
+
}
|
|
274
|
+
|
|
271
275
|
if (util.isDisturbed(stream)) {
|
|
272
276
|
throw new TypeError('disturbed')
|
|
273
277
|
}
|
package/lib/fetch/index.js
CHANGED
|
@@ -31,7 +31,7 @@ const {
|
|
|
31
31
|
determineRequestsReferrer,
|
|
32
32
|
coarsenedSharedCurrentTime
|
|
33
33
|
} = require('./util')
|
|
34
|
-
const { kState, kHeaders, kGuard, kRealm } = require('./symbols')
|
|
34
|
+
const { kState, kHeaders, kGuard, kRealm, kError } = require('./symbols')
|
|
35
35
|
const { AbortError } = require('../core/errors')
|
|
36
36
|
const assert = require('assert')
|
|
37
37
|
const { safelyExtractBody, cancelBody } = require('./body')
|
|
@@ -82,14 +82,13 @@ async function fetch (...args) {
|
|
|
82
82
|
if (this.terminated) {
|
|
83
83
|
return
|
|
84
84
|
}
|
|
85
|
+
this.terminated = { aborted }
|
|
85
86
|
|
|
86
87
|
if (this.connection) {
|
|
87
|
-
this.connection.destroy()
|
|
88
|
+
this.connection.destroy(reason)
|
|
88
89
|
this.connection = null
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
this.terminated = { aborted }
|
|
92
|
-
|
|
93
92
|
this.emit('terminated', reason)
|
|
94
93
|
}
|
|
95
94
|
})
|
|
@@ -266,8 +265,6 @@ function markResourceTiming () {
|
|
|
266
265
|
|
|
267
266
|
// https://fetch.spec.whatwg.org/#abort-fetch
|
|
268
267
|
function abortFetch (p, request, responseObject) {
|
|
269
|
-
const context = this
|
|
270
|
-
|
|
271
268
|
// 1. Let error be an "AbortError" DOMException.
|
|
272
269
|
const error = new AbortError()
|
|
273
270
|
|
|
@@ -291,7 +288,7 @@ function abortFetch (p, request, responseObject) {
|
|
|
291
288
|
// 6. If response’s body is not null and is readable, then error response’s
|
|
292
289
|
// body with error.
|
|
293
290
|
if (response.body != null) {
|
|
294
|
-
|
|
291
|
+
cancelBody(response.body, error)
|
|
295
292
|
}
|
|
296
293
|
}
|
|
297
294
|
|
|
@@ -649,7 +646,7 @@ async function mainFetch (fetchParams, recursive = false) {
|
|
|
649
646
|
nullBodyStatus.includes(internalResponse.status))
|
|
650
647
|
) {
|
|
651
648
|
internalResponse.body = null
|
|
652
|
-
context.
|
|
649
|
+
context.dump = true
|
|
653
650
|
}
|
|
654
651
|
|
|
655
652
|
// 20. If request’s integrity metadata is not the empty string, then:
|
|
@@ -1335,32 +1332,28 @@ function httpNetworkFetch (
|
|
|
1335
1332
|
return new Promise((resolve) => {
|
|
1336
1333
|
assert(!context.connection || context.connection.destroyed)
|
|
1337
1334
|
|
|
1338
|
-
|
|
1335
|
+
context.connection = {
|
|
1339
1336
|
abort: null,
|
|
1340
1337
|
controller: null,
|
|
1341
1338
|
destroyed: false,
|
|
1342
|
-
errored: false,
|
|
1343
|
-
dump: false,
|
|
1344
1339
|
destroy (err) {
|
|
1345
1340
|
if (this.destroyed) {
|
|
1346
1341
|
return
|
|
1347
1342
|
}
|
|
1348
|
-
|
|
1349
1343
|
this.destroyed = true
|
|
1350
1344
|
|
|
1345
|
+
err = err ?? new AbortError()
|
|
1346
|
+
|
|
1351
1347
|
if (this.abort) {
|
|
1352
|
-
this.abort()
|
|
1348
|
+
this.abort(err)
|
|
1353
1349
|
this.abort = null
|
|
1354
1350
|
}
|
|
1355
1351
|
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
if (this.controller) {
|
|
1352
|
+
// TODO (fix): Do we need controller here?
|
|
1353
|
+
if (context.controller) {
|
|
1361
1354
|
try {
|
|
1362
|
-
|
|
1363
|
-
|
|
1355
|
+
context.controller.error(err)
|
|
1356
|
+
context.controller = null
|
|
1364
1357
|
} catch (err) {
|
|
1365
1358
|
// Will throw TypeError if body is not readable.
|
|
1366
1359
|
if (err.name !== 'TypeError') {
|
|
@@ -1369,7 +1362,7 @@ function httpNetworkFetch (
|
|
|
1369
1362
|
}
|
|
1370
1363
|
}
|
|
1371
1364
|
}
|
|
1372
|
-
}
|
|
1365
|
+
}
|
|
1373
1366
|
|
|
1374
1367
|
// 1. Let request be fetchParams’s request.
|
|
1375
1368
|
const request = fetchParams.request
|
|
@@ -1505,10 +1498,10 @@ function httpNetworkFetch (
|
|
|
1505
1498
|
// 9. If aborted, then:
|
|
1506
1499
|
function onRequestAborted () {
|
|
1507
1500
|
// 1. Let aborted be the termination’s aborted flag.
|
|
1508
|
-
const aborted =
|
|
1501
|
+
const aborted = this.terminated.aborted
|
|
1509
1502
|
|
|
1510
1503
|
// 2. If connection uses HTTP/2, then transmit an RST_STREAM frame.
|
|
1511
|
-
connection
|
|
1504
|
+
this.connection?.destroy()
|
|
1512
1505
|
|
|
1513
1506
|
// 3. If aborted is set, then return an aborted network error.
|
|
1514
1507
|
const reason = aborted ? new AbortError() : new Error('terminated')
|
|
@@ -1529,7 +1522,7 @@ function httpNetworkFetch (
|
|
|
1529
1522
|
|
|
1530
1523
|
// 12. Let highWaterMark be a non-negative, non-NaN number, chosen by
|
|
1531
1524
|
// the user agent.
|
|
1532
|
-
const highWaterMark =
|
|
1525
|
+
const highWaterMark = 64 * 1024 // Same as nodejs fs streams.
|
|
1533
1526
|
|
|
1534
1527
|
// 13. Let sizeAlgorithm be an algorithm that accepts a chunk object
|
|
1535
1528
|
// and returns a non-negative, non-NaN, non-infinite number, chosen by the user agent.
|
|
@@ -1543,20 +1536,24 @@ function httpNetworkFetch (
|
|
|
1543
1536
|
ReadableStream = require('stream/web').ReadableStream
|
|
1544
1537
|
}
|
|
1545
1538
|
|
|
1539
|
+
let pullResolve
|
|
1540
|
+
|
|
1546
1541
|
const stream = new ReadableStream(
|
|
1547
1542
|
{
|
|
1548
1543
|
async start (controller) {
|
|
1549
|
-
|
|
1544
|
+
context.controller = controller
|
|
1550
1545
|
},
|
|
1551
|
-
async pull () {
|
|
1552
|
-
if (pullAlgorithm) {
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1546
|
+
async pull (controller) {
|
|
1547
|
+
if (!pullAlgorithm) {
|
|
1548
|
+
await new Promise((resolve) => {
|
|
1549
|
+
pullResolve = resolve
|
|
1550
|
+
})
|
|
1556
1551
|
}
|
|
1552
|
+
await pullAlgorithm(controller)
|
|
1557
1553
|
},
|
|
1558
1554
|
async cancel (reason) {
|
|
1559
|
-
|
|
1555
|
+
stream[kError] = reason
|
|
1556
|
+
await cancelAlgorithm(reason)
|
|
1560
1557
|
}
|
|
1561
1558
|
},
|
|
1562
1559
|
{ highWaterMark }
|
|
@@ -1586,7 +1583,7 @@ function httpNetworkFetch (
|
|
|
1586
1583
|
finalizeResponse(fetchParams, response)
|
|
1587
1584
|
|
|
1588
1585
|
// 2. Let aborted be the termination’s aborted flag.
|
|
1589
|
-
const aborted =
|
|
1586
|
+
const aborted = this.terminated.aborted
|
|
1590
1587
|
|
|
1591
1588
|
// 3. If aborted is set, then:
|
|
1592
1589
|
if (aborted) {
|
|
@@ -1594,15 +1591,29 @@ function httpNetworkFetch (
|
|
|
1594
1591
|
response.aborted = true
|
|
1595
1592
|
|
|
1596
1593
|
// 2. If stream is readable, error stream with an "AbortError" DOMException.
|
|
1597
|
-
|
|
1594
|
+
try {
|
|
1595
|
+
this.controller.error(new AbortError())
|
|
1596
|
+
} catch (err) {
|
|
1597
|
+
// Will throw TypeError if body is not readable.
|
|
1598
|
+
if (err.name !== 'TypeError') {
|
|
1599
|
+
throw err
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1598
1602
|
} else {
|
|
1599
1603
|
// 4. Otherwise, if stream is readable, error stream with a TypeError.
|
|
1600
|
-
|
|
1604
|
+
try {
|
|
1605
|
+
this.controller.error(new TypeError('terminated'))
|
|
1606
|
+
} catch (err) {
|
|
1607
|
+
// Will throw TypeError if body is not readable.
|
|
1608
|
+
if (err.name !== 'TypeError') {
|
|
1609
|
+
throw err
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1601
1612
|
}
|
|
1602
1613
|
|
|
1603
1614
|
// 5. If connection uses HTTP/2, then transmit an RST_STREAM frame.
|
|
1604
1615
|
// 6. Otherwise, the user agent should close connection unless it would be bad for performance to do so.
|
|
1605
|
-
connection
|
|
1616
|
+
this.connection?.destroy()
|
|
1606
1617
|
}
|
|
1607
1618
|
|
|
1608
1619
|
// 19. Return response.
|
|
@@ -1621,8 +1632,12 @@ function httpNetworkFetch (
|
|
|
1621
1632
|
},
|
|
1622
1633
|
{
|
|
1623
1634
|
decoder: null,
|
|
1635
|
+
context,
|
|
1624
1636
|
|
|
1625
1637
|
onConnect (abort) {
|
|
1638
|
+
// TODO (fix): Do we need connection here?
|
|
1639
|
+
const { connection } = this.context
|
|
1640
|
+
|
|
1626
1641
|
if (connection.destroyed) {
|
|
1627
1642
|
abort(new AbortError())
|
|
1628
1643
|
} else {
|
|
@@ -1643,19 +1658,16 @@ function httpNetworkFetch (
|
|
|
1643
1658
|
)
|
|
1644
1659
|
}
|
|
1645
1660
|
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
const body = { stream }
|
|
1649
|
-
registry.register(body, connection.abort)
|
|
1661
|
+
registry.register(stream, this.abort, this)
|
|
1650
1662
|
|
|
1651
1663
|
response = makeResponse({
|
|
1652
1664
|
status,
|
|
1653
1665
|
statusText,
|
|
1654
1666
|
headersList: headers[kHeadersList],
|
|
1655
|
-
body
|
|
1667
|
+
body: { stream }
|
|
1656
1668
|
})
|
|
1657
1669
|
|
|
1658
|
-
context.on('terminated', onResponseAborted)
|
|
1670
|
+
this.context.on('terminated', onResponseAborted)
|
|
1659
1671
|
|
|
1660
1672
|
const codings =
|
|
1661
1673
|
headers
|
|
@@ -1704,7 +1716,7 @@ function httpNetworkFetch (
|
|
|
1704
1716
|
this.decoder.on('drain', resume)
|
|
1705
1717
|
}
|
|
1706
1718
|
|
|
1707
|
-
pullAlgorithm = async () => {
|
|
1719
|
+
pullAlgorithm = async (controller) => {
|
|
1708
1720
|
// 4. Set bytes to the result of handling content codings given
|
|
1709
1721
|
// codings and bytes.
|
|
1710
1722
|
let bytes
|
|
@@ -1720,10 +1732,6 @@ function httpNetworkFetch (
|
|
|
1720
1732
|
}
|
|
1721
1733
|
}
|
|
1722
1734
|
|
|
1723
|
-
if (!connection.controller) {
|
|
1724
|
-
return
|
|
1725
|
-
}
|
|
1726
|
-
|
|
1727
1735
|
if (bytes === undefined) {
|
|
1728
1736
|
// 2. Otherwise, if the bytes transmission for response’s message
|
|
1729
1737
|
// body is done normally and stream is readable, then close
|
|
@@ -1731,13 +1739,7 @@ function httpNetworkFetch (
|
|
|
1731
1739
|
// abort these in-parallel steps.
|
|
1732
1740
|
finalizeResponse(fetchParams, response)
|
|
1733
1741
|
|
|
1734
|
-
|
|
1735
|
-
context.off('terminated', onRequestAborted)
|
|
1736
|
-
|
|
1737
|
-
connection.controller.close()
|
|
1738
|
-
connection.controller = null
|
|
1739
|
-
|
|
1740
|
-
connection.destroy()
|
|
1742
|
+
controller.close()
|
|
1741
1743
|
|
|
1742
1744
|
return
|
|
1743
1745
|
}
|
|
@@ -1747,27 +1749,28 @@ function httpNetworkFetch (
|
|
|
1747
1749
|
|
|
1748
1750
|
// 6. If bytes is failure, then terminate the ongoing fetch.
|
|
1749
1751
|
if (bytes instanceof Error) {
|
|
1750
|
-
context.terminate({ reason: bytes })
|
|
1752
|
+
this.context.terminate({ reason: bytes })
|
|
1751
1753
|
return
|
|
1752
1754
|
}
|
|
1753
1755
|
|
|
1754
1756
|
// 7. Enqueue a Uint8Array wrapping an ArrayBuffer containing bytes
|
|
1755
|
-
//
|
|
1756
|
-
|
|
1757
|
+
// into stream.
|
|
1758
|
+
controller.enqueue(new Uint8Array(bytes))
|
|
1757
1759
|
|
|
1758
1760
|
// 8. If stream is errored, then terminate the ongoing fetch.
|
|
1759
|
-
if (
|
|
1760
|
-
context.terminate({ reason:
|
|
1761
|
+
if (stream[kError]) {
|
|
1762
|
+
this.context.terminate({ reason: stream[kError] })
|
|
1761
1763
|
return
|
|
1762
1764
|
}
|
|
1763
1765
|
|
|
1764
1766
|
// 9. If stream doesn’t need more data ask the user agent to suspend
|
|
1765
|
-
//
|
|
1766
|
-
return
|
|
1767
|
+
// the ongoing fetch.
|
|
1768
|
+
return controller.desiredSize > 0
|
|
1767
1769
|
}
|
|
1768
1770
|
|
|
1769
|
-
if (
|
|
1770
|
-
|
|
1771
|
+
if (pullResolve) {
|
|
1772
|
+
pullResolve()
|
|
1773
|
+
pullResolve = null
|
|
1771
1774
|
}
|
|
1772
1775
|
|
|
1773
1776
|
resolve(response)
|
|
@@ -1776,7 +1779,7 @@ function httpNetworkFetch (
|
|
|
1776
1779
|
},
|
|
1777
1780
|
|
|
1778
1781
|
onData (chunk) {
|
|
1779
|
-
if (
|
|
1782
|
+
if (this.context.dump) {
|
|
1780
1783
|
return
|
|
1781
1784
|
}
|
|
1782
1785
|
|
|
@@ -1798,17 +1801,18 @@ function httpNetworkFetch (
|
|
|
1798
1801
|
return this.decoder.write(bytes)
|
|
1799
1802
|
},
|
|
1800
1803
|
|
|
1801
|
-
|
|
1804
|
+
onComplete () {
|
|
1805
|
+
registry.unregister(this)
|
|
1806
|
+
|
|
1802
1807
|
this.decoder.end()
|
|
1803
1808
|
},
|
|
1804
1809
|
|
|
1805
1810
|
onError (error) {
|
|
1806
|
-
|
|
1807
|
-
context.off('terminated', onRequestAborted)
|
|
1811
|
+
registry.unregister(this)
|
|
1808
1812
|
|
|
1809
|
-
|
|
1813
|
+
this.decoder?.destroy(error)
|
|
1810
1814
|
|
|
1811
|
-
context.terminate({ reason: error })
|
|
1815
|
+
this.context.terminate({ reason: error })
|
|
1812
1816
|
|
|
1813
1817
|
if (!response) {
|
|
1814
1818
|
resolve(makeNetworkError(error))
|
package/lib/fetch/symbols.js
CHANGED