urllib 3.19.3 → 3.21.0
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 +9 -8
- package/dist/commonjs/HttpAgent.js +1 -1
- package/dist/commonjs/HttpClient.d.ts +7 -0
- package/dist/commonjs/HttpClient.js +49 -25
- package/dist/commonjs/HttpClientError.d.ts +19 -0
- package/dist/commonjs/HttpClientError.js +29 -0
- package/dist/commonjs/Response.d.ts +5 -0
- package/dist/commonjs/diagnosticsChannel.js +45 -2
- package/dist/commonjs/index.d.ts +1 -0
- package/dist/commonjs/index.js +16 -1
- package/dist/commonjs/package.json +3 -1
- package/dist/commonjs/symbols.d.ts +5 -0
- package/dist/commonjs/symbols.js +5 -0
- package/dist/commonjs/utils.js +6 -6
- package/dist/esm/HttpAgent.js +1 -1
- package/dist/esm/HttpClient.d.ts +7 -0
- package/dist/esm/HttpClient.js +50 -26
- package/dist/esm/HttpClientError.d.ts +19 -0
- package/dist/esm/HttpClientError.js +23 -0
- package/dist/esm/Response.d.ts +5 -0
- package/dist/esm/diagnosticsChannel.js +45 -2
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/package.json +3 -1
- package/dist/esm/symbols.d.ts +5 -0
- package/dist/esm/symbols.js +5 -0
- package/dist/esm/utils.js +6 -6
- package/package.json +33 -30
- package/src/HttpAgent.ts +1 -1
- package/src/HttpClient.ts +54 -26
- package/src/HttpClientError.ts +34 -0
- package/src/Response.ts +5 -0
- package/src/diagnosticsChannel.ts +48 -2
- package/src/index.ts +3 -2
- package/src/symbols.ts +5 -0
package/README.md
CHANGED
@@ -290,14 +290,15 @@ Fork [undici benchmarks script](https://github.com/fengmk2/undici/blob/urllib-be
|
|
290
290
|
|
291
291
|
|[<img src="https://avatars.githubusercontent.com/u/156269?v=4" width="100px;"/><br/><sub><b>fengmk2</b></sub>](https://github.com/fengmk2)<br/>|[<img src="https://avatars.githubusercontent.com/u/985607?v=4" width="100px;"/><br/><sub><b>dead-horse</b></sub>](https://github.com/dead-horse)<br/>|[<img src="https://avatars.githubusercontent.com/u/32174276?v=4" width="100px;"/><br/><sub><b>semantic-release-bot</b></sub>](https://github.com/semantic-release-bot)<br/>|[<img src="https://avatars.githubusercontent.com/u/288288?v=4" width="100px;"/><br/><sub><b>xingrz</b></sub>](https://github.com/xingrz)<br/>|[<img src="https://avatars.githubusercontent.com/u/360661?v=4" width="100px;"/><br/><sub><b>popomore</b></sub>](https://github.com/popomore)<br/>|[<img src="https://avatars.githubusercontent.com/u/327019?v=4" width="100px;"/><br/><sub><b>JacksonTian</b></sub>](https://github.com/JacksonTian)<br/>|
|
292
292
|
| :---: | :---: | :---: | :---: | :---: | :---: |
|
293
|
-
|[<img src="https://avatars.githubusercontent.com/u/543405?v=4" width="100px;"/><br/><sub><b>ibigbug</b></sub>](https://github.com/ibigbug)<br/>|[<img src="https://avatars.githubusercontent.com/u/14790466?v=4" width="100px;"/><br/><sub><b>greenkeeperio-bot</b></sub>](https://github.com/greenkeeperio-bot)<br/>|[<img src="https://avatars.githubusercontent.com/u/227713?v=4" width="100px;"/><br/><sub><b>atian25</b></sub>](https://github.com/atian25)<br/>|[<img src="https://avatars.githubusercontent.com/u/6897780?v=4" width="100px;"/><br/><sub><b>killagu</b></sub>](https://github.com/killagu)<br/>|[<img src="https://avatars.githubusercontent.com/u/5381764?v=4" width="100px;"/><br/><sub><b>paambaati</b></sub>](https://github.com/paambaati)<br/>|[<img src="https://avatars.githubusercontent.com/u/
|
294
|
-
|[<img src="https://avatars.githubusercontent.com/u/
|
295
|
-
|[<img src="https://avatars.githubusercontent.com/u/
|
296
|
-
|[<img src="https://avatars.githubusercontent.com/u/
|
297
|
-
|[<img src="https://avatars.githubusercontent.com/u/
|
298
|
-
[<img src="https://avatars.githubusercontent.com/u/
|
299
|
-
|
300
|
-
|
293
|
+
|[<img src="https://avatars.githubusercontent.com/u/543405?v=4" width="100px;"/><br/><sub><b>ibigbug</b></sub>](https://github.com/ibigbug)<br/>|[<img src="https://avatars.githubusercontent.com/u/14790466?v=4" width="100px;"/><br/><sub><b>greenkeeperio-bot</b></sub>](https://github.com/greenkeeperio-bot)<br/>|[<img src="https://avatars.githubusercontent.com/u/227713?v=4" width="100px;"/><br/><sub><b>atian25</b></sub>](https://github.com/atian25)<br/>|[<img src="https://avatars.githubusercontent.com/u/6897780?v=4" width="100px;"/><br/><sub><b>killagu</b></sub>](https://github.com/killagu)<br/>|[<img src="https://avatars.githubusercontent.com/u/5381764?v=4" width="100px;"/><br/><sub><b>paambaati</b></sub>](https://github.com/paambaati)<br/>|[<img src="https://avatars.githubusercontent.com/u/199635?v=4" width="100px;"/><br/><sub><b>tremby</b></sub>](https://github.com/tremby)<br/>|
|
294
|
+
|[<img src="https://avatars.githubusercontent.com/u/1433247?v=4" width="100px;"/><br/><sub><b>denghongcai</b></sub>](https://github.com/denghongcai)<br/>|[<img src="https://avatars.githubusercontent.com/u/4635838?v=4" width="100px;"/><br/><sub><b>gemwuu</b></sub>](https://github.com/gemwuu)<br/>|[<img src="https://avatars.githubusercontent.com/u/2842176?v=4" width="100px;"/><br/><sub><b>XadillaX</b></sub>](https://github.com/XadillaX)<br/>|[<img src="https://avatars.githubusercontent.com/u/1147375?v=4" width="100px;"/><br/><sub><b>alsotang</b></sub>](https://github.com/alsotang)<br/>|[<img src="https://avatars.githubusercontent.com/u/546535?v=4" width="100px;"/><br/><sub><b>leoner</b></sub>](https://github.com/leoner)<br/>|[<img src="https://avatars.githubusercontent.com/u/19908330?v=4" width="100px;"/><br/><sub><b>hyj1991</b></sub>](https://github.com/hyj1991)<br/>|
|
295
|
+
|[<img src="https://avatars.githubusercontent.com/u/1747852?v=4" width="100px;"/><br/><sub><b>isayme</b></sub>](https://github.com/isayme)<br/>|[<img src="https://avatars.githubusercontent.com/u/252317?v=4" width="100px;"/><br/><sub><b>cyjake</b></sub>](https://github.com/cyjake)<br/>|[<img src="https://avatars.githubusercontent.com/u/5856440?v=4" width="100px;"/><br/><sub><b>whxaxes</b></sub>](https://github.com/whxaxes)<br/>|[<img src="https://avatars.githubusercontent.com/u/309219?v=4" width="100px;"/><br/><sub><b>chadxz</b></sub>](https://github.com/chadxz)<br/>|[<img src="https://avatars.githubusercontent.com/u/2055702?v=4" width="100px;"/><br/><sub><b>adapt0</b></sub>](https://github.com/adapt0)<br/>|[<img src="https://avatars.githubusercontent.com/u/5139554?v=4" width="100px;"/><br/><sub><b>danielwpz</b></sub>](https://github.com/danielwpz)<br/>|
|
296
|
+
|[<img src="https://avatars.githubusercontent.com/u/5127897?v=4" width="100px;"/><br/><sub><b>danielsss</b></sub>](https://github.com/danielsss)<br/>|[<img src="https://avatars.githubusercontent.com/u/3367820?v=4" width="100px;"/><br/><sub><b>Jeff-Tian</b></sub>](https://github.com/Jeff-Tian)<br/>|[<img src="https://avatars.githubusercontent.com/u/17075261?v=4" width="100px;"/><br/><sub><b>nick-ng</b></sub>](https://github.com/nick-ng)<br/>|[<img src="https://avatars.githubusercontent.com/u/1706595?v=4" width="100px;"/><br/><sub><b>rishavsharan</b></sub>](https://github.com/rishavsharan)<br/>|[<img src="https://avatars.githubusercontent.com/u/1886161?v=4" width="100px;"/><br/><sub><b>willizm</b></sub>](https://github.com/willizm)<br/>|[<img src="https://avatars.githubusercontent.com/u/7227589?v=4" width="100px;"/><br/><sub><b>davidkhala</b></sub>](https://github.com/davidkhala)<br/>|
|
297
|
+
|[<img src="https://avatars.githubusercontent.com/u/535479?v=4" width="100px;"/><br/><sub><b>aleafs</b></sub>](https://github.com/aleafs)<br/>|[<img src="https://avatars.githubusercontent.com/u/3689968?v=4" width="100px;"/><br/><sub><b>Amunu</b></sub>](https://github.com/Amunu)<br/>|[<img src="https://avatars.githubusercontent.com/in/9426?v=4" width="100px;"/><br/><sub><b>azure-pipelines[bot]</b></sub>](https://github.com/apps/azure-pipelines)<br/>|[<img src="https://avatars.githubusercontent.com/u/108602490?v=4" width="100px;"/><br/><sub><b>capsice</b></sub>](https://github.com/capsice)<br/>|[<img src="https://avatars.githubusercontent.com/u/1281323?v=4" width="100px;"/><br/><sub><b>changzhiwin</b></sub>](https://github.com/changzhiwin)<br/>|[<img src="https://avatars.githubusercontent.com/u/929503?v=4" width="100px;"/><br/><sub><b>yuzhigang33</b></sub>](https://github.com/yuzhigang33)<br/>|
|
298
|
+
|[<img src="https://avatars.githubusercontent.com/u/5574625?v=4" width="100px;"/><br/><sub><b>elrrrrrrr</b></sub>](https://github.com/elrrrrrrr)<br/>|[<img src="https://avatars.githubusercontent.com/u/981128?v=4" width="100px;"/><br/><sub><b>fishbar</b></sub>](https://github.com/fishbar)<br/>|[<img src="https://avatars.githubusercontent.com/u/1207064?v=4" width="100px;"/><br/><sub><b>gxcsoccer</b></sub>](https://github.com/gxcsoccer)<br/>|[<img src="https://avatars.githubusercontent.com/u/17476119?v=4" width="100px;"/><br/><sub><b>mars-coder</b></sub>](https://github.com/mars-coder)<br/>|[<img src="https://avatars.githubusercontent.com/u/929179?v=4" width="100px;"/><br/><sub><b>rockdai</b></sub>](https://github.com/rockdai)<br/>|[<img src="https://avatars.githubusercontent.com/u/2196373?v=4" width="100px;"/><br/><sub><b>dickeylth</b></sub>](https://github.com/dickeylth)<br/>|
|
299
|
+
[<img src="https://avatars.githubusercontent.com/u/13050025?v=4" width="100px;"/><br/><sub><b>aladdin-add</b></sub>](https://github.com/aladdin-add)<br/>
|
300
|
+
|
301
|
+
This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Mon Dec 04 2023 00:13:39 GMT+0800`.
|
301
302
|
|
302
303
|
<!-- GITCONTRIBUTOR_END -->
|
303
304
|
|
@@ -68,7 +68,7 @@ class HttpAgent extends undici_1.Agent {
|
|
68
68
|
}
|
69
69
|
const family = (0, node_net_1.isIP)(hostname);
|
70
70
|
if (family === 4 || family === 6) {
|
71
|
-
// if request hostname is ip, custom lookup won't
|
71
|
+
// if request hostname is ip, custom lookup won't execute
|
72
72
|
if (!this.#checkAddress(hostname, family)) {
|
73
73
|
throw new IllegalAddressError(hostname, hostname, family);
|
74
74
|
}
|
@@ -3,6 +3,7 @@
|
|
3
3
|
/// <reference types="node" />
|
4
4
|
import { EventEmitter } from 'node:events';
|
5
5
|
import { LookupFunction } from 'node:net';
|
6
|
+
import { Dispatcher } from 'undici';
|
6
7
|
import { CheckAddressFunction } from './HttpAgent.js';
|
7
8
|
import { RequestURL, RequestOptions, RequestMeta } from './Request.js';
|
8
9
|
import { RawResponseWithMeta, HttpClientResponse } from './Response.js';
|
@@ -34,6 +35,10 @@ export type ClientOptions = {
|
|
34
35
|
* socketPath string | null (optional) - Default: null - An IPC endpoint, either Unix domain socket or Windows named pipe
|
35
36
|
*/
|
36
37
|
socketPath?: string | null;
|
38
|
+
/**
|
39
|
+
* connect timeout, default is 10000ms
|
40
|
+
*/
|
41
|
+
timeout?: number;
|
37
42
|
};
|
38
43
|
};
|
39
44
|
export declare const HEADER_USER_AGENT: string;
|
@@ -48,6 +53,8 @@ export type ResponseDiagnosticsMessage = {
|
|
48
53
|
export declare class HttpClient extends EventEmitter {
|
49
54
|
#private;
|
50
55
|
constructor(clientOptions?: ClientOptions);
|
56
|
+
getDispatcher(): Dispatcher;
|
57
|
+
setDispatcher(dispatcher: Dispatcher): void;
|
51
58
|
request<T = any>(url: RequestURL, options?: RequestOptions): Promise<HttpClientResponse<T>>;
|
52
59
|
curl<T = any>(url: RequestURL, options?: RequestOptions): Promise<HttpClientResponse<T>>;
|
53
60
|
}
|
@@ -29,6 +29,7 @@ const HttpAgent_js_1 = require("./HttpAgent.js");
|
|
29
29
|
const utils_js_1 = require("./utils.js");
|
30
30
|
const symbols_js_1 = __importDefault(require("./symbols.js"));
|
31
31
|
const diagnosticsChannel_js_1 = require("./diagnosticsChannel.js");
|
32
|
+
const HttpClientError_js_1 = require("./HttpClientError.js");
|
32
33
|
const PROTO_RE = /^https?:\/\//i;
|
33
34
|
const FormData = undici_1.FormData ?? formdata_node_1.FormData;
|
34
35
|
// impl promise pipeline on Node.js 14
|
@@ -65,15 +66,7 @@ class BlobFromStream {
|
|
65
66
|
return 'Blob';
|
66
67
|
}
|
67
68
|
}
|
68
|
-
|
69
|
-
constructor(timeout, options) {
|
70
|
-
const message = `Request timeout for ${timeout} ms`;
|
71
|
-
super(message, options);
|
72
|
-
this.name = this.constructor.name;
|
73
|
-
Error.captureStackTrace(this, this.constructor);
|
74
|
-
}
|
75
|
-
}
|
76
|
-
exports.HEADER_USER_AGENT = (0, default_user_agent_1.default)('node-urllib', '3.19.3');
|
69
|
+
exports.HEADER_USER_AGENT = (0, default_user_agent_1.default)('node-urllib', '3.21.0');
|
77
70
|
function getFileName(stream) {
|
78
71
|
const filePath = stream.path;
|
79
72
|
if (filePath) {
|
@@ -94,15 +87,26 @@ class HttpClient extends node_events_1.EventEmitter {
|
|
94
87
|
constructor(clientOptions) {
|
95
88
|
super();
|
96
89
|
this.#defaultArgs = clientOptions?.defaultArgs;
|
97
|
-
if (clientOptions?.lookup || clientOptions?.checkAddress
|
90
|
+
if (clientOptions?.lookup || clientOptions?.checkAddress) {
|
98
91
|
this.#dispatcher = new HttpAgent_js_1.HttpAgent({
|
99
92
|
lookup: clientOptions.lookup,
|
100
93
|
checkAddress: clientOptions.checkAddress,
|
101
94
|
connect: clientOptions.connect,
|
102
95
|
});
|
103
96
|
}
|
97
|
+
else if (clientOptions?.connect) {
|
98
|
+
this.#dispatcher = new undici_1.Agent({
|
99
|
+
connect: clientOptions.connect,
|
100
|
+
});
|
101
|
+
}
|
104
102
|
(0, diagnosticsChannel_js_1.initDiagnosticsChannel)();
|
105
103
|
}
|
104
|
+
getDispatcher() {
|
105
|
+
return this.#dispatcher ?? (0, undici_1.getGlobalDispatcher)();
|
106
|
+
}
|
107
|
+
setDispatcher(dispatcher) {
|
108
|
+
this.#dispatcher = dispatcher;
|
109
|
+
}
|
106
110
|
async request(url, options) {
|
107
111
|
return await this.#requestInternal(url, options);
|
108
112
|
}
|
@@ -569,14 +573,17 @@ class HttpClient extends node_events_1.EventEmitter {
|
|
569
573
|
}
|
570
574
|
return clientResponse;
|
571
575
|
}
|
572
|
-
catch (
|
573
|
-
debug('Request#%d throw error: %s', requestId,
|
574
|
-
let err =
|
576
|
+
catch (rawError) {
|
577
|
+
debug('Request#%d throw error: %s', requestId, rawError);
|
578
|
+
let err = rawError;
|
575
579
|
if (err.name === 'HeadersTimeoutError') {
|
576
|
-
err = new HttpClientRequestTimeoutError(headersTimeout, { cause:
|
580
|
+
err = new HttpClientError_js_1.HttpClientRequestTimeoutError(headersTimeout, { cause: err });
|
577
581
|
}
|
578
582
|
else if (err.name === 'BodyTimeoutError') {
|
579
|
-
err = new HttpClientRequestTimeoutError(bodyTimeout, { cause:
|
583
|
+
err = new HttpClientError_js_1.HttpClientRequestTimeoutError(bodyTimeout, { cause: err });
|
584
|
+
}
|
585
|
+
else if (err.code === 'UND_ERR_CONNECT_TIMEOUT') {
|
586
|
+
err = new HttpClientError_js_1.HttpClientConnectTimeoutError(err.message, err.code, { cause: err });
|
580
587
|
}
|
581
588
|
else if (err.code === 'UND_ERR_SOCKET' || err.code === 'ECONNRESET') {
|
582
589
|
// auto retry on socket error, https://github.com/node-modules/urllib/issues/454
|
@@ -599,7 +606,7 @@ class HttpClient extends node_events_1.EventEmitter {
|
|
599
606
|
res.requestUrls.push(requestUrl.href);
|
600
607
|
}
|
601
608
|
res.rt = (0, utils_js_1.performanceTime)(requestStartTime);
|
602
|
-
this.#updateSocketInfo(socketInfo, internalOpaque);
|
609
|
+
this.#updateSocketInfo(socketInfo, internalOpaque, rawError);
|
603
610
|
channels.response.publish({
|
604
611
|
request: reqMeta,
|
605
612
|
response: res,
|
@@ -620,21 +627,38 @@ class HttpClient extends node_events_1.EventEmitter {
|
|
620
627
|
throw err;
|
621
628
|
}
|
622
629
|
}
|
623
|
-
#updateSocketInfo(socketInfo, internalOpaque) {
|
624
|
-
const socket = internalOpaque[symbols_js_1.default.kRequestSocket];
|
630
|
+
#updateSocketInfo(socketInfo, internalOpaque, err) {
|
631
|
+
const socket = internalOpaque[symbols_js_1.default.kRequestSocket] ?? err?.[symbols_js_1.default.kErrorSocket];
|
625
632
|
if (socket) {
|
626
633
|
socketInfo.id = socket[symbols_js_1.default.kSocketId];
|
627
634
|
socketInfo.handledRequests = socket[symbols_js_1.default.kHandledRequests];
|
628
635
|
socketInfo.handledResponses = socket[symbols_js_1.default.kHandledResponses];
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
636
|
+
if (socket[symbols_js_1.default.kSocketLocalAddress]) {
|
637
|
+
socketInfo.localAddress = socket[symbols_js_1.default.kSocketLocalAddress];
|
638
|
+
socketInfo.localPort = socket[symbols_js_1.default.kSocketLocalPort];
|
639
|
+
}
|
640
|
+
if (socket.remoteAddress) {
|
641
|
+
socketInfo.remoteAddress = socket.remoteAddress;
|
642
|
+
socketInfo.remotePort = socket.remotePort;
|
643
|
+
socketInfo.remoteFamily = socket.remoteFamily;
|
644
|
+
}
|
634
645
|
socketInfo.bytesRead = socket.bytesRead;
|
635
646
|
socketInfo.bytesWritten = socket.bytesWritten;
|
636
|
-
|
637
|
-
|
647
|
+
if (socket[symbols_js_1.default.kSocketConnectErrorTime]) {
|
648
|
+
socketInfo.connectErrorTime = socket[symbols_js_1.default.kSocketConnectErrorTime];
|
649
|
+
if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) {
|
650
|
+
socketInfo.attemptedRemoteAddresses = socket.autoSelectFamilyAttemptedAddresses;
|
651
|
+
}
|
652
|
+
socketInfo.connectProtocol = socket[symbols_js_1.default.kSocketConnectProtocol];
|
653
|
+
socketInfo.connectHost = socket[symbols_js_1.default.kSocketConnectHost];
|
654
|
+
socketInfo.connectPort = socket[symbols_js_1.default.kSocketConnectPort];
|
655
|
+
}
|
656
|
+
if (socket[symbols_js_1.default.kSocketConnectedTime]) {
|
657
|
+
socketInfo.connectedTime = socket[symbols_js_1.default.kSocketConnectedTime];
|
658
|
+
}
|
659
|
+
if (socket[symbols_js_1.default.kSocketRequestEndTime]) {
|
660
|
+
socketInfo.lastRequestEndTime = socket[symbols_js_1.default.kSocketRequestEndTime];
|
661
|
+
}
|
638
662
|
socket[symbols_js_1.default.kSocketRequestEndTime] = new Date();
|
639
663
|
}
|
640
664
|
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import type { RawResponseWithMeta, SocketInfo } from './Response.js';
|
2
|
+
import type { IncomingHttpHeaders } from './IncomingHttpHeaders.js';
|
3
|
+
interface ErrorOptions {
|
4
|
+
cause?: Error;
|
5
|
+
}
|
6
|
+
export declare class HttpClientRequestError extends Error {
|
7
|
+
status?: number;
|
8
|
+
headers?: IncomingHttpHeaders;
|
9
|
+
socket?: SocketInfo;
|
10
|
+
res?: RawResponseWithMeta;
|
11
|
+
}
|
12
|
+
export declare class HttpClientRequestTimeoutError extends HttpClientRequestError {
|
13
|
+
constructor(timeout: number, options: ErrorOptions);
|
14
|
+
}
|
15
|
+
export declare class HttpClientConnectTimeoutError extends HttpClientRequestError {
|
16
|
+
code: string;
|
17
|
+
constructor(message: string, code: string, options: ErrorOptions);
|
18
|
+
}
|
19
|
+
export {};
|
@@ -0,0 +1,29 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.HttpClientConnectTimeoutError = exports.HttpClientRequestTimeoutError = exports.HttpClientRequestError = void 0;
|
4
|
+
class HttpClientRequestError extends Error {
|
5
|
+
status;
|
6
|
+
headers;
|
7
|
+
socket;
|
8
|
+
res;
|
9
|
+
}
|
10
|
+
exports.HttpClientRequestError = HttpClientRequestError;
|
11
|
+
class HttpClientRequestTimeoutError extends HttpClientRequestError {
|
12
|
+
constructor(timeout, options) {
|
13
|
+
const message = `Request timeout for ${timeout} ms`;
|
14
|
+
super(message, options);
|
15
|
+
this.name = this.constructor.name;
|
16
|
+
Error.captureStackTrace(this, this.constructor);
|
17
|
+
}
|
18
|
+
}
|
19
|
+
exports.HttpClientRequestTimeoutError = HttpClientRequestTimeoutError;
|
20
|
+
class HttpClientConnectTimeoutError extends HttpClientRequestError {
|
21
|
+
code;
|
22
|
+
constructor(message, code, options) {
|
23
|
+
super(message, options);
|
24
|
+
this.name = this.constructor.name;
|
25
|
+
this.code = code;
|
26
|
+
Error.captureStackTrace(this, this.constructor);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
exports.HttpClientConnectTimeoutError = HttpClientConnectTimeoutError;
|
@@ -13,7 +13,12 @@ export type SocketInfo = {
|
|
13
13
|
handledRequests: number;
|
14
14
|
handledResponses: number;
|
15
15
|
connectedTime?: Date;
|
16
|
+
connectErrorTime?: Date;
|
16
17
|
lastRequestEndTime?: Date;
|
18
|
+
attemptedRemoteAddresses?: string[];
|
19
|
+
connectProtocol?: string;
|
20
|
+
connectHost?: string;
|
21
|
+
connectPort?: string;
|
17
22
|
};
|
18
23
|
/**
|
19
24
|
* https://eggjs.org/en/core/httpclient.html#timing-boolean
|
@@ -7,6 +7,7 @@ exports.initDiagnosticsChannel = void 0;
|
|
7
7
|
const node_diagnostics_channel_1 = __importDefault(require("node:diagnostics_channel"));
|
8
8
|
const node_perf_hooks_1 = require("node:perf_hooks");
|
9
9
|
const node_util_1 = require("node:util");
|
10
|
+
const node_net_1 = require("node:net");
|
10
11
|
const symbols_js_1 = __importDefault(require("./symbols.js"));
|
11
12
|
const utils_js_1 = require("./utils.js");
|
12
13
|
const debug = (0, node_util_1.debuglog)('urllib:DiagnosticsChannel');
|
@@ -38,8 +39,23 @@ function formatSocket(socket) {
|
|
38
39
|
localPort: socket[symbols_js_1.default.kSocketLocalPort],
|
39
40
|
remoteAddress: socket.remoteAddress,
|
40
41
|
remotePort: socket.remotePort,
|
42
|
+
attemptedAddresses: socket.autoSelectFamilyAttemptedAddresses,
|
43
|
+
connecting: socket.connecting,
|
41
44
|
};
|
42
45
|
}
|
46
|
+
// make sure error contains socket info
|
47
|
+
const kDestroy = Symbol('kDestroy');
|
48
|
+
node_net_1.Socket.prototype[kDestroy] = node_net_1.Socket.prototype.destroy;
|
49
|
+
node_net_1.Socket.prototype.destroy = function (err) {
|
50
|
+
if (err) {
|
51
|
+
Object.defineProperty(err, symbols_js_1.default.kErrorSocket, {
|
52
|
+
// don't show on console log
|
53
|
+
enumerable: false,
|
54
|
+
value: this,
|
55
|
+
});
|
56
|
+
}
|
57
|
+
return this[kDestroy](err);
|
58
|
+
};
|
43
59
|
function initDiagnosticsChannel() {
|
44
60
|
// makre sure init global DiagnosticsChannel once
|
45
61
|
if (initedDiagnosticsChannel)
|
@@ -69,10 +85,34 @@ function initDiagnosticsChannel() {
|
|
69
85
|
opaque[symbols_js_1.default.kRequestTiming].queuing = (0, utils_js_1.performanceTime)(opaque[symbols_js_1.default.kRequestStartTime]);
|
70
86
|
});
|
71
87
|
// diagnosticsChannel.channel('undici:client:beforeConnect')
|
72
|
-
|
88
|
+
subscribe('undici:client:connectError', (message, name) => {
|
89
|
+
const { error, connectParams } = message;
|
90
|
+
let { socket } = message;
|
91
|
+
if (!socket && error[symbols_js_1.default.kErrorSocket]) {
|
92
|
+
socket = error[symbols_js_1.default.kErrorSocket];
|
93
|
+
}
|
94
|
+
if (socket) {
|
95
|
+
socket[symbols_js_1.default.kSocketId] = (0, utils_js_1.globalId)('UndiciSocket');
|
96
|
+
socket[symbols_js_1.default.kSocketConnectErrorTime] = new Date();
|
97
|
+
socket[symbols_js_1.default.kHandledRequests] = 0;
|
98
|
+
socket[symbols_js_1.default.kHandledResponses] = 0;
|
99
|
+
// copy local address to symbol, avoid them be reset after request error throw
|
100
|
+
if (socket.localAddress) {
|
101
|
+
socket[symbols_js_1.default.kSocketLocalAddress] = socket.localAddress;
|
102
|
+
socket[symbols_js_1.default.kSocketLocalPort] = socket.localPort;
|
103
|
+
}
|
104
|
+
socket[symbols_js_1.default.kSocketConnectProtocol] = connectParams.protocol;
|
105
|
+
socket[symbols_js_1.default.kSocketConnectHost] = connectParams.host;
|
106
|
+
socket[symbols_js_1.default.kSocketConnectPort] = connectParams.port;
|
107
|
+
debug('[%s] Socket#%d connectError, connectParams: %o, error: %s, (sock: %o)', name, socket[symbols_js_1.default.kSocketId], connectParams, error.message, formatSocket(socket));
|
108
|
+
}
|
109
|
+
else {
|
110
|
+
debug('[%s] connectError, connectParams: %o, error: %o', name, connectParams, error);
|
111
|
+
}
|
112
|
+
});
|
73
113
|
// This message is published after a connection is established.
|
74
114
|
subscribe('undici:client:connected', (message, name) => {
|
75
|
-
const { socket } = message;
|
115
|
+
const { socket, connectParams } = message;
|
76
116
|
socket[symbols_js_1.default.kSocketId] = (0, utils_js_1.globalId)('UndiciSocket');
|
77
117
|
socket[symbols_js_1.default.kSocketStartTime] = node_perf_hooks_1.performance.now();
|
78
118
|
socket[symbols_js_1.default.kSocketConnectedTime] = new Date();
|
@@ -81,6 +121,9 @@ function initDiagnosticsChannel() {
|
|
81
121
|
// copy local address to symbol, avoid them be reset after request error throw
|
82
122
|
socket[symbols_js_1.default.kSocketLocalAddress] = socket.localAddress;
|
83
123
|
socket[symbols_js_1.default.kSocketLocalPort] = socket.localPort;
|
124
|
+
socket[symbols_js_1.default.kSocketConnectProtocol] = connectParams.protocol;
|
125
|
+
socket[symbols_js_1.default.kSocketConnectHost] = connectParams.host;
|
126
|
+
socket[symbols_js_1.default.kSocketConnectPort] = connectParams.port;
|
84
127
|
debug('[%s] Socket#%d connected (sock: %o)', name, socket[symbols_js_1.default.kSocketId], formatSocket(socket));
|
85
128
|
});
|
86
129
|
// This message is published right before the first byte of the request is written to the socket.
|
package/dist/commonjs/index.d.ts
CHANGED
@@ -6,6 +6,7 @@ export { HttpClient, HttpClient as HttpClient2, HEADER_USER_AGENT as USER_AGENT,
|
|
6
6
|
export { RequestOptions, RequestOptions as RequestOptions2, RequestURL, HttpMethod, FixJSONCtlCharsHandler, FixJSONCtlChars, } from './Request.js';
|
7
7
|
export { SocketInfo, Timing, RawResponseWithMeta, HttpClientResponse, } from './Response.js';
|
8
8
|
export { IncomingHttpHeaders, } from './IncomingHttpHeaders.js';
|
9
|
+
export * from './HttpClientError.js';
|
9
10
|
declare const _default: {
|
10
11
|
request: typeof request;
|
11
12
|
curl: typeof curl;
|
package/dist/commonjs/index.js
CHANGED
@@ -1,4 +1,18 @@
|
|
1
1
|
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
15
|
+
};
|
2
16
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
18
|
};
|
@@ -25,7 +39,7 @@ async function request(url, options) {
|
|
25
39
|
return await httpclient.request(url, options);
|
26
40
|
}
|
27
41
|
exports.request = request;
|
28
|
-
// export curl method is keep compatible with
|
42
|
+
// export curl method is keep compatible with urllib.curl()
|
29
43
|
// ```ts
|
30
44
|
// import * as urllib from 'urllib';
|
31
45
|
// urllib.curl(url);
|
@@ -46,6 +60,7 @@ var HttpClient_js_2 = require("./HttpClient.js");
|
|
46
60
|
Object.defineProperty(exports, "HttpClient", { enumerable: true, get: function () { return HttpClient_js_2.HttpClient; } });
|
47
61
|
Object.defineProperty(exports, "HttpClient2", { enumerable: true, get: function () { return HttpClient_js_2.HttpClient; } });
|
48
62
|
Object.defineProperty(exports, "USER_AGENT", { enumerable: true, get: function () { return HttpClient_js_2.HEADER_USER_AGENT; } });
|
63
|
+
__exportStar(require("./HttpClientError.js"), exports);
|
49
64
|
exports.default = {
|
50
65
|
request,
|
51
66
|
curl,
|
@@ -2,9 +2,13 @@ declare const _default: {
|
|
2
2
|
kSocketId: symbol;
|
3
3
|
kSocketStartTime: symbol;
|
4
4
|
kSocketConnectedTime: symbol;
|
5
|
+
kSocketConnectErrorTime: symbol;
|
5
6
|
kSocketRequestEndTime: symbol;
|
6
7
|
kSocketLocalAddress: symbol;
|
7
8
|
kSocketLocalPort: symbol;
|
9
|
+
kSocketConnectHost: symbol;
|
10
|
+
kSocketConnectPort: symbol;
|
11
|
+
kSocketConnectProtocol: symbol;
|
8
12
|
kHandledRequests: symbol;
|
9
13
|
kHandledResponses: symbol;
|
10
14
|
kRequestSocket: symbol;
|
@@ -13,5 +17,6 @@ declare const _default: {
|
|
13
17
|
kEnableRequestTiming: symbol;
|
14
18
|
kRequestTiming: symbol;
|
15
19
|
kRequestOriginalOpaque: symbol;
|
20
|
+
kErrorSocket: symbol;
|
16
21
|
};
|
17
22
|
export default _default;
|
package/dist/commonjs/symbols.js
CHANGED
@@ -4,9 +4,13 @@ exports.default = {
|
|
4
4
|
kSocketId: Symbol('socket id'),
|
5
5
|
kSocketStartTime: Symbol('socket start time'),
|
6
6
|
kSocketConnectedTime: Symbol('socket connected time'),
|
7
|
+
kSocketConnectErrorTime: Symbol('socket connectError time'),
|
7
8
|
kSocketRequestEndTime: Symbol('socket request end time'),
|
8
9
|
kSocketLocalAddress: Symbol('socket local address'),
|
9
10
|
kSocketLocalPort: Symbol('socket local port'),
|
11
|
+
kSocketConnectHost: Symbol('socket connect params: host'),
|
12
|
+
kSocketConnectPort: Symbol('socket connect params: port'),
|
13
|
+
kSocketConnectProtocol: Symbol('socket connect params: protocol'),
|
10
14
|
kHandledRequests: Symbol('handled requests per socket'),
|
11
15
|
kHandledResponses: Symbol('handled responses per socket'),
|
12
16
|
kRequestSocket: Symbol('request on the socket'),
|
@@ -15,4 +19,5 @@ exports.default = {
|
|
15
19
|
kEnableRequestTiming: Symbol('enable request timing or not'),
|
16
20
|
kRequestTiming: Symbol('request timing'),
|
17
21
|
kRequestOriginalOpaque: Symbol('request original opaque'),
|
22
|
+
kErrorSocket: Symbol('socket of error'),
|
18
23
|
};
|
package/dist/commonjs/utils.js
CHANGED
@@ -5,12 +5,12 @@ const node_crypto_1 = require("node:crypto");
|
|
5
5
|
const node_stream_1 = require("node:stream");
|
6
6
|
const node_perf_hooks_1 = require("node:perf_hooks");
|
7
7
|
const JSONCtlCharsMap = {
|
8
|
-
'"': '\\"',
|
9
|
-
'\\': '\\\\',
|
10
|
-
'\b': '\\b',
|
11
|
-
'\f': '\\f',
|
12
|
-
'\n': '\\n',
|
13
|
-
'\r': '\\r',
|
8
|
+
'"': '\\"', // \u0022
|
9
|
+
'\\': '\\\\', // \u005c
|
10
|
+
'\b': '\\b', // \u0008
|
11
|
+
'\f': '\\f', // \u000c
|
12
|
+
'\n': '\\n', // \u000a
|
13
|
+
'\r': '\\r', // \u000d
|
14
14
|
'\t': '\\t', // \u0009
|
15
15
|
};
|
16
16
|
/* eslint no-control-regex: "off"*/
|
package/dist/esm/HttpAgent.js
CHANGED
@@ -62,7 +62,7 @@ export class HttpAgent extends Agent {
|
|
62
62
|
}
|
63
63
|
const family = isIP(hostname);
|
64
64
|
if (family === 4 || family === 6) {
|
65
|
-
// if request hostname is ip, custom lookup won't
|
65
|
+
// if request hostname is ip, custom lookup won't execute
|
66
66
|
if (!this.#checkAddress(hostname, family)) {
|
67
67
|
throw new IllegalAddressError(hostname, hostname, family);
|
68
68
|
}
|
package/dist/esm/HttpClient.d.ts
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
/// <reference types="node" resolution-mode="require"/>
|
4
4
|
import { EventEmitter } from 'node:events';
|
5
5
|
import { LookupFunction } from 'node:net';
|
6
|
+
import { Dispatcher } from 'undici';
|
6
7
|
import { CheckAddressFunction } from './HttpAgent.js';
|
7
8
|
import { RequestURL, RequestOptions, RequestMeta } from './Request.js';
|
8
9
|
import { RawResponseWithMeta, HttpClientResponse } from './Response.js';
|
@@ -34,6 +35,10 @@ export type ClientOptions = {
|
|
34
35
|
* socketPath string | null (optional) - Default: null - An IPC endpoint, either Unix domain socket or Windows named pipe
|
35
36
|
*/
|
36
37
|
socketPath?: string | null;
|
38
|
+
/**
|
39
|
+
* connect timeout, default is 10000ms
|
40
|
+
*/
|
41
|
+
timeout?: number;
|
37
42
|
};
|
38
43
|
};
|
39
44
|
export declare const HEADER_USER_AGENT: string;
|
@@ -48,6 +53,8 @@ export type ResponseDiagnosticsMessage = {
|
|
48
53
|
export declare class HttpClient extends EventEmitter {
|
49
54
|
#private;
|
50
55
|
constructor(clientOptions?: ClientOptions);
|
56
|
+
getDispatcher(): Dispatcher;
|
57
|
+
setDispatcher(dispatcher: Dispatcher): void;
|
51
58
|
request<T = any>(url: RequestURL, options?: RequestOptions): Promise<HttpClientResponse<T>>;
|
52
59
|
curl<T = any>(url: RequestURL, options?: RequestOptions): Promise<HttpClientResponse<T>>;
|
53
60
|
}
|