rust-fetch 2.1.0 → 2.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 +1 -1
- package/node.js +30 -1
- package/package.json +1 -1
- package/rust_fetch.js +9 -9
- package/rust_fetch_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -381,7 +381,7 @@ Large JSON is dominated by `JSON.parse`, which both clients pay; the remaining g
|
|
|
381
381
|
- [ ] Upload progress tracking: not possible on top of `fetch()`, which has no upload progress events
|
|
382
382
|
- [ ] WebSocket support
|
|
383
383
|
- Handled by the runtime, not by rust-fetch:
|
|
384
|
-
- **Connection pooling:** browsers pool connections for `fetch()`; in Node.js rust-fetch
|
|
384
|
+
- **Connection pooling:** browsers pool connections for `fetch()`; in Node.js rust-fetch keeps up to 256 keep-alive connections per origin and queues further requests until one is free. If you install your own `http.globalAgent` / `https.globalAgent`, or set limits on Node's, that agent is used instead.
|
|
385
385
|
- **Proxies:** in Node.js, install a proxy agent as `http.globalAgent` / `https.globalAgent` (for example from `https-proxy-agent`). In browsers, use the system settings.
|
|
386
386
|
- **HTTP/2:** browsers negotiate it automatically; the Node.js transport uses HTTP/1.1 with keep-alive.
|
|
387
387
|
|
package/node.js
CHANGED
|
@@ -17,6 +17,35 @@ import { initSync } from './rust_fetch.js';
|
|
|
17
17
|
|
|
18
18
|
initSync({ module: readFileSync(new URL('./rust_fetch_bg.wasm', import.meta.url)) });
|
|
19
19
|
|
|
20
|
+
// Node's default global agents open a socket for every request that finds no
|
|
21
|
+
// idle one, but keep only 256 of them idle afterwards. Under a burst the rest
|
|
22
|
+
// are closed and sit in TIME_WAIT, and once the ephemeral port range is used
|
|
23
|
+
// up every connect fails with EADDRNOTAVAIL. A bounded pool that keeps all of
|
|
24
|
+
// its sockets queues requests instead, reusing the same connections.
|
|
25
|
+
const MAX_SOCKETS = 256;
|
|
26
|
+
const POOL_OPTIONS = { keepAlive: true, scheduling: 'lifo', timeout: 5000, maxSockets: MAX_SOCKETS, maxFreeSockets: MAX_SOCKETS };
|
|
27
|
+
const pools = new Map([
|
|
28
|
+
[http, new http.Agent(POOL_OPTIONS)],
|
|
29
|
+
[https, new https.Agent(POOL_OPTIONS)],
|
|
30
|
+
]);
|
|
31
|
+
// The options Node's own global agents are created with. Newer versions also
|
|
32
|
+
// list unset ones (e.g. `proxyEnv: undefined` unless NODE_USE_ENV_PROXY is on).
|
|
33
|
+
const NODE_AGENT_OPTIONS = { keepAlive: true, scheduling: 'lifo', timeout: 5000, noDelay: true, defaultPort: 443, protocol: 'https:' };
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* The bounded pool while `globalAgent` is still Node's unbounded default;
|
|
37
|
+
* an agent the application installed (a proxy, TLS options, its own limits)
|
|
38
|
+
* is used as is.
|
|
39
|
+
*/
|
|
40
|
+
function agentFor(transport) {
|
|
41
|
+
const global = transport.globalAgent;
|
|
42
|
+
const isNodeDefault =
|
|
43
|
+
global.constructor === transport.Agent &&
|
|
44
|
+
global.maxSockets === Infinity &&
|
|
45
|
+
Object.entries(global.options).every(([key, value]) => value == null || NODE_AGENT_OPTIONS[key] === value);
|
|
46
|
+
return isNodeDefault ? pools.get(transport) : global;
|
|
47
|
+
}
|
|
48
|
+
|
|
20
49
|
const MAX_REDIRECTS = 20;
|
|
21
50
|
const REDIRECT_STATUSES = new Set([301, 302, 303, 307, 308]);
|
|
22
51
|
const ACCEPT_ENCODING = typeof zlib.zstdDecompressSync === 'function' ? 'gzip, deflate, br, zstd' : 'gzip, deflate, br';
|
|
@@ -126,7 +155,7 @@ function withoutHeaders(headers, names) {
|
|
|
126
155
|
function send(state, method, url, headers, body, redirects, resolve, reject) {
|
|
127
156
|
if (state.cancelled) return;
|
|
128
157
|
const transport = url.protocol === 'https:' ? https : http;
|
|
129
|
-
const request = transport.request(url, { method, headers }, (response) => {
|
|
158
|
+
const request = transport.request(url, { method, headers, agent: agentFor(transport) }, (response) => {
|
|
130
159
|
const status = response.statusCode;
|
|
131
160
|
const location = response.headers.location;
|
|
132
161
|
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"Asem Qaffaf <asem@qaffaf.com>"
|
|
6
6
|
],
|
|
7
7
|
"description": "A reliable HTTP client for JavaScript and TypeScript, written in Rust and compiled to WebAssembly: timeouts, retries, typed errors and interceptors, faster than fetch() in Node.js",
|
|
8
|
-
"version": "2.1.
|
|
8
|
+
"version": "2.1.1",
|
|
9
9
|
"license": "MIT OR Apache-2.0",
|
|
10
10
|
"repository": {
|
|
11
11
|
"type": "git",
|
package/rust_fetch.js
CHANGED
|
@@ -561,7 +561,7 @@ function __wbg_get_imports() {
|
|
|
561
561
|
const ret = clearTimeout(arg0);
|
|
562
562
|
return ret;
|
|
563
563
|
},
|
|
564
|
-
|
|
564
|
+
__wbg_clearTimeout_de7e2788a4701f78: function(arg0) {
|
|
565
565
|
clearTimeout(arg0);
|
|
566
566
|
},
|
|
567
567
|
__wbg_close_185286988f30f252: function() { return handleError(function (arg0) {
|
|
@@ -570,7 +570,7 @@ function __wbg_get_imports() {
|
|
|
570
570
|
__wbg_close_748f26698dabe269: function() { return handleError(function (arg0) {
|
|
571
571
|
arg0.close();
|
|
572
572
|
}, arguments); },
|
|
573
|
-
|
|
573
|
+
__wbg_decode_0775197308e59c17: function() { return handleError(function (arg0, arg1) {
|
|
574
574
|
const ret = arg0.decode(arg1);
|
|
575
575
|
return ret;
|
|
576
576
|
}, arguments); },
|
|
@@ -589,7 +589,7 @@ function __wbg_get_imports() {
|
|
|
589
589
|
const ret = Object.entries(arg0);
|
|
590
590
|
return ret;
|
|
591
591
|
},
|
|
592
|
-
|
|
592
|
+
__wbg_fetch_4dd9052d4418f5a3: function() { return handleError(function (arg0) {
|
|
593
593
|
const ret = fetch(arg0);
|
|
594
594
|
return ret;
|
|
595
595
|
}, arguments); },
|
|
@@ -734,14 +734,14 @@ function __wbg_get_imports() {
|
|
|
734
734
|
const ret = new Object();
|
|
735
735
|
return ret;
|
|
736
736
|
},
|
|
737
|
+
__wbg_new_777668d2bcf04e9b: function() {
|
|
738
|
+
const ret = new TextDecoder();
|
|
739
|
+
return ret;
|
|
740
|
+
},
|
|
737
741
|
__wbg_new_83ca405eae412a62: function() { return handleError(function () {
|
|
738
742
|
const ret = new Headers();
|
|
739
743
|
return ret;
|
|
740
744
|
}, arguments); },
|
|
741
|
-
__wbg_new_cdac6c2ae368ec54: function() {
|
|
742
|
-
const ret = new TextDecoder();
|
|
743
|
-
return ret;
|
|
744
|
-
},
|
|
745
745
|
__wbg_new_from_slice_9a868026ffa4208a: function(arg0, arg1) {
|
|
746
746
|
const ret = new Uint8Array(getArrayU8FromWasm0(arg0, arg1));
|
|
747
747
|
return ret;
|
|
@@ -796,7 +796,7 @@ function __wbg_get_imports() {
|
|
|
796
796
|
const ret = JSON.parse(getStringFromWasm0(arg0, arg1));
|
|
797
797
|
return ret;
|
|
798
798
|
}, arguments); },
|
|
799
|
-
|
|
799
|
+
__wbg_parse_9d2d081cff35f81a: function() { return handleError(function (arg0) {
|
|
800
800
|
const ret = JSON.parse(arg0);
|
|
801
801
|
return ret;
|
|
802
802
|
}, arguments); },
|
|
@@ -839,7 +839,7 @@ function __wbg_get_imports() {
|
|
|
839
839
|
__wbg_respond_c102fabcc79e5ef0: function() { return handleError(function (arg0, arg1) {
|
|
840
840
|
arg0.respond(arg1 >>> 0);
|
|
841
841
|
}, arguments); },
|
|
842
|
-
|
|
842
|
+
__wbg_setTimeout_36fb298700cc9ab9: function(arg0, arg1) {
|
|
843
843
|
const ret = setTimeout(arg0, arg1);
|
|
844
844
|
return ret;
|
|
845
845
|
},
|
package/rust_fetch_bg.wasm
CHANGED
|
Binary file
|