urllib 3.20.0 → 3.22.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/dist/commonjs/HttpAgent.js +1 -1
- package/dist/commonjs/HttpClient.d.ts +20 -0
- package/dist/commonjs/HttpClient.js +70 -35
- 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 +3 -0
- package/dist/commonjs/index.js +29 -10
- package/dist/commonjs/symbols.d.ts +5 -0
- package/dist/commonjs/symbols.js +5 -0
- package/dist/esm/HttpAgent.js +1 -1
- package/dist/esm/HttpClient.d.ts +20 -0
- package/dist/esm/HttpClient.js +60 -25
- 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 +3 -0
- package/dist/esm/index.js +13 -9
- package/dist/esm/symbols.d.ts +5 -0
- package/dist/esm/symbols.js +5 -0
- package/package.json +5 -4
- package/src/HttpAgent.ts +1 -1
- package/src/HttpClient.ts +74 -26
- package/src/HttpClientError.ts +34 -0
- package/src/Response.ts +5 -0
- package/src/diagnosticsChannel.ts +48 -2
- package/src/index.ts +15 -10
- package/src/symbols.ts +5 -0
@@ -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
|
}
|
@@ -42,6 +42,11 @@ export type ClientOptions = {
|
|
42
42
|
};
|
43
43
|
};
|
44
44
|
export declare const HEADER_USER_AGENT: string;
|
45
|
+
export type RequestContext = {
|
46
|
+
retries: number;
|
47
|
+
socketErrorRetries: number;
|
48
|
+
requestStartTime?: number;
|
49
|
+
};
|
45
50
|
export type RequestDiagnosticsMessage = {
|
46
51
|
request: RequestMeta;
|
47
52
|
};
|
@@ -50,11 +55,26 @@ export type ResponseDiagnosticsMessage = {
|
|
50
55
|
response: RawResponseWithMeta;
|
51
56
|
error?: Error;
|
52
57
|
};
|
58
|
+
export interface PoolStat {
|
59
|
+
/** Number of open socket connections in this pool. */
|
60
|
+
connected: number;
|
61
|
+
/** Number of open socket connections in this pool that do not have an active request. */
|
62
|
+
free: number;
|
63
|
+
/** Number of pending requests across all clients in this pool. */
|
64
|
+
pending: number;
|
65
|
+
/** Number of queued requests across all clients in this pool. */
|
66
|
+
queued: number;
|
67
|
+
/** Number of currently active requests across all clients in this pool. */
|
68
|
+
running: number;
|
69
|
+
/** Number of active, pending, or queued requests across all clients in this pool. */
|
70
|
+
size: number;
|
71
|
+
}
|
53
72
|
export declare class HttpClient extends EventEmitter {
|
54
73
|
#private;
|
55
74
|
constructor(clientOptions?: ClientOptions);
|
56
75
|
getDispatcher(): Dispatcher;
|
57
76
|
setDispatcher(dispatcher: Dispatcher): void;
|
77
|
+
getDispatcherPoolStats(): Record<string, PoolStat>;
|
58
78
|
request<T = any>(url: RequestURL, options?: RequestOptions): Promise<HttpClientResponse<T>>;
|
59
79
|
curl<T = any>(url: RequestURL, options?: RequestOptions): Promise<HttpClientResponse<T>>;
|
60
80
|
}
|
@@ -17,6 +17,7 @@ const node_fs_1 = require("node:fs");
|
|
17
17
|
const node_url_1 = require("node:url");
|
18
18
|
const node_perf_hooks_1 = require("node:perf_hooks");
|
19
19
|
const undici_1 = require("undici");
|
20
|
+
const symbols_js_1 = __importDefault(require("undici/lib/core/symbols.js"));
|
20
21
|
const formdata_node_1 = require("formdata-node");
|
21
22
|
const form_data_encoder_1 = require("form-data-encoder");
|
22
23
|
const default_user_agent_1 = __importDefault(require("default-user-agent"));
|
@@ -27,8 +28,9 @@ const pump_1 = __importDefault(require("pump"));
|
|
27
28
|
const formstream_1 = __importDefault(require("formstream"));
|
28
29
|
const HttpAgent_js_1 = require("./HttpAgent.js");
|
29
30
|
const utils_js_1 = require("./utils.js");
|
30
|
-
const
|
31
|
+
const symbols_js_2 = __importDefault(require("./symbols.js"));
|
31
32
|
const diagnosticsChannel_js_1 = require("./diagnosticsChannel.js");
|
33
|
+
const HttpClientError_js_1 = require("./HttpClientError.js");
|
32
34
|
const PROTO_RE = /^https?:\/\//i;
|
33
35
|
const FormData = undici_1.FormData ?? formdata_node_1.FormData;
|
34
36
|
// impl promise pipeline on Node.js 14
|
@@ -65,15 +67,7 @@ class BlobFromStream {
|
|
65
67
|
return 'Blob';
|
66
68
|
}
|
67
69
|
}
|
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.20.0');
|
70
|
+
exports.HEADER_USER_AGENT = (0, default_user_agent_1.default)('node-urllib', '3.22.0');
|
77
71
|
function getFileName(stream) {
|
78
72
|
const filePath = stream.path;
|
79
73
|
if (filePath) {
|
@@ -114,10 +108,31 @@ class HttpClient extends node_events_1.EventEmitter {
|
|
114
108
|
setDispatcher(dispatcher) {
|
115
109
|
this.#dispatcher = dispatcher;
|
116
110
|
}
|
111
|
+
getDispatcherPoolStats() {
|
112
|
+
const agent = this.getDispatcher();
|
113
|
+
// origin => Pool Instance
|
114
|
+
const clients = agent[symbols_js_1.default.kClients];
|
115
|
+
const poolStatsMap = {};
|
116
|
+
for (const [key, ref] of clients) {
|
117
|
+
const pool = ref.deref();
|
118
|
+
const stats = pool?.stats;
|
119
|
+
if (!stats)
|
120
|
+
continue;
|
121
|
+
poolStatsMap[key] = {
|
122
|
+
connected: stats.connected,
|
123
|
+
free: stats.free,
|
124
|
+
pending: stats.pending,
|
125
|
+
queued: stats.queued,
|
126
|
+
running: stats.running,
|
127
|
+
size: stats.size,
|
128
|
+
};
|
129
|
+
}
|
130
|
+
return poolStatsMap;
|
131
|
+
}
|
117
132
|
async request(url, options) {
|
118
133
|
return await this.#requestInternal(url, options);
|
119
134
|
}
|
120
|
-
// alias to request, keep compatible with
|
135
|
+
// alias to request, keep compatible with urllib@2 HttpClient.curl
|
121
136
|
async curl(url, options) {
|
122
137
|
return await this.request(url, options);
|
123
138
|
}
|
@@ -183,11 +198,11 @@ class HttpClient extends node_events_1.EventEmitter {
|
|
183
198
|
const originalOpaque = args.opaque;
|
184
199
|
// using opaque to diagnostics channel, binding request and socket
|
185
200
|
const internalOpaque = {
|
186
|
-
[
|
187
|
-
[
|
188
|
-
[
|
189
|
-
[
|
190
|
-
[
|
201
|
+
[symbols_js_2.default.kRequestId]: requestId,
|
202
|
+
[symbols_js_2.default.kRequestStartTime]: requestStartTime,
|
203
|
+
[symbols_js_2.default.kEnableRequestTiming]: !!args.timing,
|
204
|
+
[symbols_js_2.default.kRequestTiming]: timing,
|
205
|
+
[symbols_js_2.default.kRequestOriginalOpaque]: originalOpaque,
|
191
206
|
};
|
192
207
|
const reqMeta = {
|
193
208
|
requestId,
|
@@ -580,14 +595,17 @@ class HttpClient extends node_events_1.EventEmitter {
|
|
580
595
|
}
|
581
596
|
return clientResponse;
|
582
597
|
}
|
583
|
-
catch (
|
584
|
-
debug('Request#%d throw error: %s', requestId,
|
585
|
-
let err =
|
598
|
+
catch (rawError) {
|
599
|
+
debug('Request#%d throw error: %s', requestId, rawError);
|
600
|
+
let err = rawError;
|
586
601
|
if (err.name === 'HeadersTimeoutError') {
|
587
|
-
err = new HttpClientRequestTimeoutError(headersTimeout, { cause:
|
602
|
+
err = new HttpClientError_js_1.HttpClientRequestTimeoutError(headersTimeout, { cause: err });
|
588
603
|
}
|
589
604
|
else if (err.name === 'BodyTimeoutError') {
|
590
|
-
err = new HttpClientRequestTimeoutError(bodyTimeout, { cause:
|
605
|
+
err = new HttpClientError_js_1.HttpClientRequestTimeoutError(bodyTimeout, { cause: err });
|
606
|
+
}
|
607
|
+
else if (err.code === 'UND_ERR_CONNECT_TIMEOUT') {
|
608
|
+
err = new HttpClientError_js_1.HttpClientConnectTimeoutError(err.message, err.code, { cause: err });
|
591
609
|
}
|
592
610
|
else if (err.code === 'UND_ERR_SOCKET' || err.code === 'ECONNRESET') {
|
593
611
|
// auto retry on socket error, https://github.com/node-modules/urllib/issues/454
|
@@ -610,7 +628,7 @@ class HttpClient extends node_events_1.EventEmitter {
|
|
610
628
|
res.requestUrls.push(requestUrl.href);
|
611
629
|
}
|
612
630
|
res.rt = (0, utils_js_1.performanceTime)(requestStartTime);
|
613
|
-
this.#updateSocketInfo(socketInfo, internalOpaque);
|
631
|
+
this.#updateSocketInfo(socketInfo, internalOpaque, rawError);
|
614
632
|
channels.response.publish({
|
615
633
|
request: reqMeta,
|
616
634
|
response: res,
|
@@ -631,22 +649,39 @@ class HttpClient extends node_events_1.EventEmitter {
|
|
631
649
|
throw err;
|
632
650
|
}
|
633
651
|
}
|
634
|
-
#updateSocketInfo(socketInfo, internalOpaque) {
|
635
|
-
const socket = internalOpaque[
|
652
|
+
#updateSocketInfo(socketInfo, internalOpaque, err) {
|
653
|
+
const socket = internalOpaque[symbols_js_2.default.kRequestSocket] ?? err?.[symbols_js_2.default.kErrorSocket];
|
636
654
|
if (socket) {
|
637
|
-
socketInfo.id = socket[
|
638
|
-
socketInfo.handledRequests = socket[
|
639
|
-
socketInfo.handledResponses = socket[
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
655
|
+
socketInfo.id = socket[symbols_js_2.default.kSocketId];
|
656
|
+
socketInfo.handledRequests = socket[symbols_js_2.default.kHandledRequests];
|
657
|
+
socketInfo.handledResponses = socket[symbols_js_2.default.kHandledResponses];
|
658
|
+
if (socket[symbols_js_2.default.kSocketLocalAddress]) {
|
659
|
+
socketInfo.localAddress = socket[symbols_js_2.default.kSocketLocalAddress];
|
660
|
+
socketInfo.localPort = socket[symbols_js_2.default.kSocketLocalPort];
|
661
|
+
}
|
662
|
+
if (socket.remoteAddress) {
|
663
|
+
socketInfo.remoteAddress = socket.remoteAddress;
|
664
|
+
socketInfo.remotePort = socket.remotePort;
|
665
|
+
socketInfo.remoteFamily = socket.remoteFamily;
|
666
|
+
}
|
645
667
|
socketInfo.bytesRead = socket.bytesRead;
|
646
668
|
socketInfo.bytesWritten = socket.bytesWritten;
|
647
|
-
|
648
|
-
|
649
|
-
|
669
|
+
if (socket[symbols_js_2.default.kSocketConnectErrorTime]) {
|
670
|
+
socketInfo.connectErrorTime = socket[symbols_js_2.default.kSocketConnectErrorTime];
|
671
|
+
if (Array.isArray(socket.autoSelectFamilyAttemptedAddresses)) {
|
672
|
+
socketInfo.attemptedRemoteAddresses = socket.autoSelectFamilyAttemptedAddresses;
|
673
|
+
}
|
674
|
+
socketInfo.connectProtocol = socket[symbols_js_2.default.kSocketConnectProtocol];
|
675
|
+
socketInfo.connectHost = socket[symbols_js_2.default.kSocketConnectHost];
|
676
|
+
socketInfo.connectPort = socket[symbols_js_2.default.kSocketConnectPort];
|
677
|
+
}
|
678
|
+
if (socket[symbols_js_2.default.kSocketConnectedTime]) {
|
679
|
+
socketInfo.connectedTime = socket[symbols_js_2.default.kSocketConnectedTime];
|
680
|
+
}
|
681
|
+
if (socket[symbols_js_2.default.kSocketRequestEndTime]) {
|
682
|
+
socketInfo.lastRequestEndTime = socket[symbols_js_2.default.kSocketRequestEndTime];
|
683
|
+
}
|
684
|
+
socket[symbols_js_2.default.kSocketRequestEndTime] = new Date();
|
650
685
|
}
|
651
686
|
}
|
652
687
|
}
|
@@ -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
@@ -1,4 +1,6 @@
|
|
1
|
+
import { HttpClient } from './HttpClient.js';
|
1
2
|
import { RequestOptions, RequestURL } from './Request.js';
|
3
|
+
export declare function getDefaultHttpClient(): HttpClient;
|
2
4
|
export declare function request<T = any>(url: RequestURL, options?: RequestOptions): Promise<import("./Response.js").HttpClientResponse<T>>;
|
3
5
|
export declare function curl<T = any>(url: RequestURL, options?: RequestOptions): Promise<import("./Response.js").HttpClientResponse<T>>;
|
4
6
|
export { MockAgent, ProxyAgent, Agent, Dispatcher, setGlobalDispatcher, getGlobalDispatcher, } from 'undici';
|
@@ -6,6 +8,7 @@ export { HttpClient, HttpClient as HttpClient2, HEADER_USER_AGENT as USER_AGENT,
|
|
6
8
|
export { RequestOptions, RequestOptions as RequestOptions2, RequestURL, HttpMethod, FixJSONCtlCharsHandler, FixJSONCtlChars, } from './Request.js';
|
7
9
|
export { SocketInfo, Timing, RawResponseWithMeta, HttpClientResponse, } from './Response.js';
|
8
10
|
export { IncomingHttpHeaders, } from './IncomingHttpHeaders.js';
|
11
|
+
export * from './HttpClientError.js';
|
9
12
|
declare const _default: {
|
10
13
|
request: typeof request;
|
11
14
|
curl: typeof curl;
|
package/dist/commonjs/index.js
CHANGED
@@ -1,28 +1,46 @@
|
|
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
|
};
|
5
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
exports.USER_AGENT = exports.HttpClient2 = exports.HttpClient = exports.getGlobalDispatcher = exports.setGlobalDispatcher = exports.Dispatcher = exports.Agent = exports.ProxyAgent = exports.MockAgent = exports.curl = exports.request = void 0;
|
20
|
+
exports.USER_AGENT = exports.HttpClient2 = exports.HttpClient = exports.getGlobalDispatcher = exports.setGlobalDispatcher = exports.Dispatcher = exports.Agent = exports.ProxyAgent = exports.MockAgent = exports.curl = exports.request = exports.getDefaultHttpClient = void 0;
|
7
21
|
const ylru_1 = __importDefault(require("ylru"));
|
8
22
|
const HttpClient_js_1 = require("./HttpClient.js");
|
9
|
-
let
|
10
|
-
const
|
23
|
+
let httpClient;
|
24
|
+
const domainSocketHttpClients = new ylru_1.default(50);
|
25
|
+
function getDefaultHttpClient() {
|
26
|
+
if (!httpClient) {
|
27
|
+
httpClient = new HttpClient_js_1.HttpClient();
|
28
|
+
}
|
29
|
+
return httpClient;
|
30
|
+
}
|
31
|
+
exports.getDefaultHttpClient = getDefaultHttpClient;
|
11
32
|
async function request(url, options) {
|
12
33
|
if (options?.socketPath) {
|
13
|
-
let domainSocketHttpclient =
|
34
|
+
let domainSocketHttpclient = domainSocketHttpClients.get(options.socketPath);
|
14
35
|
if (!domainSocketHttpclient) {
|
15
36
|
domainSocketHttpclient = new HttpClient_js_1.HttpClient({
|
16
37
|
connect: { socketPath: options.socketPath },
|
17
38
|
});
|
18
|
-
|
39
|
+
domainSocketHttpClients.set(options.socketPath, domainSocketHttpclient);
|
19
40
|
}
|
20
41
|
return await domainSocketHttpclient.request(url, options);
|
21
42
|
}
|
22
|
-
|
23
|
-
httpclient = new HttpClient_js_1.HttpClient({});
|
24
|
-
}
|
25
|
-
return await httpclient.request(url, options);
|
43
|
+
return await getDefaultHttpClient().request(url, options);
|
26
44
|
}
|
27
45
|
exports.request = request;
|
28
46
|
// export curl method is keep compatible with urllib.curl()
|
@@ -41,11 +59,12 @@ Object.defineProperty(exports, "Agent", { enumerable: true, get: function () { r
|
|
41
59
|
Object.defineProperty(exports, "Dispatcher", { enumerable: true, get: function () { return undici_1.Dispatcher; } });
|
42
60
|
Object.defineProperty(exports, "setGlobalDispatcher", { enumerable: true, get: function () { return undici_1.setGlobalDispatcher; } });
|
43
61
|
Object.defineProperty(exports, "getGlobalDispatcher", { enumerable: true, get: function () { return undici_1.getGlobalDispatcher; } });
|
44
|
-
// HttpClient2 is keep compatible with
|
62
|
+
// HttpClient2 is keep compatible with urllib@2 HttpClient2
|
45
63
|
var HttpClient_js_2 = require("./HttpClient.js");
|
46
64
|
Object.defineProperty(exports, "HttpClient", { enumerable: true, get: function () { return HttpClient_js_2.HttpClient; } });
|
47
65
|
Object.defineProperty(exports, "HttpClient2", { enumerable: true, get: function () { return HttpClient_js_2.HttpClient; } });
|
48
66
|
Object.defineProperty(exports, "USER_AGENT", { enumerable: true, get: function () { return HttpClient_js_2.HEADER_USER_AGENT; } });
|
67
|
+
__exportStar(require("./HttpClientError.js"), exports);
|
49
68
|
exports.default = {
|
50
69
|
request,
|
51
70
|
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/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
@@ -42,6 +42,11 @@ export type ClientOptions = {
|
|
42
42
|
};
|
43
43
|
};
|
44
44
|
export declare const HEADER_USER_AGENT: string;
|
45
|
+
export type RequestContext = {
|
46
|
+
retries: number;
|
47
|
+
socketErrorRetries: number;
|
48
|
+
requestStartTime?: number;
|
49
|
+
};
|
45
50
|
export type RequestDiagnosticsMessage = {
|
46
51
|
request: RequestMeta;
|
47
52
|
};
|
@@ -50,11 +55,26 @@ export type ResponseDiagnosticsMessage = {
|
|
50
55
|
response: RawResponseWithMeta;
|
51
56
|
error?: Error;
|
52
57
|
};
|
58
|
+
export interface PoolStat {
|
59
|
+
/** Number of open socket connections in this pool. */
|
60
|
+
connected: number;
|
61
|
+
/** Number of open socket connections in this pool that do not have an active request. */
|
62
|
+
free: number;
|
63
|
+
/** Number of pending requests across all clients in this pool. */
|
64
|
+
pending: number;
|
65
|
+
/** Number of queued requests across all clients in this pool. */
|
66
|
+
queued: number;
|
67
|
+
/** Number of currently active requests across all clients in this pool. */
|
68
|
+
running: number;
|
69
|
+
/** Number of active, pending, or queued requests across all clients in this pool. */
|
70
|
+
size: number;
|
71
|
+
}
|
53
72
|
export declare class HttpClient extends EventEmitter {
|
54
73
|
#private;
|
55
74
|
constructor(clientOptions?: ClientOptions);
|
56
75
|
getDispatcher(): Dispatcher;
|
57
76
|
setDispatcher(dispatcher: Dispatcher): void;
|
77
|
+
getDispatcherPoolStats(): Record<string, PoolStat>;
|
58
78
|
request<T = any>(url: RequestURL, options?: RequestOptions): Promise<HttpClientResponse<T>>;
|
59
79
|
curl<T = any>(url: RequestURL, options?: RequestOptions): Promise<HttpClientResponse<T>>;
|
60
80
|
}
|