urllib 3.16.1 → 3.17.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 +5 -7
- package/package.json +5 -3
- package/src/HttpClient.ts +79 -12
- package/src/Request.ts +23 -5
- package/src/Response.ts +4 -0
- package/src/cjs/HttpClient.d.ts +10 -2
- package/src/cjs/HttpClient.js +62 -9
- package/src/cjs/Request.d.ts +22 -5
- package/src/cjs/Response.d.ts +4 -0
- package/src/cjs/diagnosticsChannel.js +42 -10
- package/src/cjs/index.d.ts +1 -1
- package/src/cjs/symbols.d.ts +4 -0
- package/src/cjs/symbols.js +4 -0
- package/src/diagnosticsChannel.ts +49 -12
- package/src/esm/HttpClient.d.ts +10 -2
- package/src/esm/HttpClient.js +62 -9
- package/src/esm/Request.d.ts +22 -5
- package/src/esm/Response.d.ts +4 -0
- package/src/esm/diagnosticsChannel.js +42 -10
- package/src/esm/index.d.ts +1 -1
- package/src/esm/index.js +1 -1
- package/src/esm/symbols.d.ts +4 -0
- package/src/esm/symbols.js +4 -0
- package/src/index.ts +4 -1
- package/src/symbols.ts +4 -0
package/src/esm/Request.d.ts
CHANGED
@@ -67,11 +67,16 @@ export type RequestOptions = {
|
|
67
67
|
headers?: IncomingHttpHeaders;
|
68
68
|
/**
|
69
69
|
* Request timeout in milliseconds for connecting phase and response receiving phase.
|
70
|
-
* Defaults to
|
71
|
-
* TIMEOUT, both are 5s. You can use timeout: 5000 to tell urllib use same timeout on two phase or set them seperately such as
|
70
|
+
* Defaults is `5000`, both are 5 seconds. You can use timeout: 5000 to tell urllib use same timeout on two phase or set them separately such as
|
72
71
|
* timeout: [3000, 5000], which will set connecting timeout to 3s and response 5s.
|
73
72
|
*/
|
74
73
|
timeout?: number | number[];
|
74
|
+
/**
|
75
|
+
* Default is `4000`, 4 seconds - The timeout after which a socket without active requests will time out.
|
76
|
+
* Monitors time between activity on a connected socket.
|
77
|
+
* This value may be overridden by *keep-alive* hints from the server. See [MDN: HTTP - Headers - Keep-Alive directives](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Keep-Alive#directives) for more details.
|
78
|
+
*/
|
79
|
+
keepAliveTimeout?: number;
|
75
80
|
/**
|
76
81
|
* username:password used in HTTP Basic Authorization.
|
77
82
|
* Alias to `headers.authorization = xxx`
|
@@ -89,7 +94,7 @@ export type RequestOptions = {
|
|
89
94
|
formatRedirectUrl?: (a: any, b: any) => void;
|
90
95
|
/** Before request hook, you can change every thing here. */
|
91
96
|
beforeRequest?: (...args: any[]) => void;
|
92
|
-
/** Accept `gzip, br` response content and auto decode it, default is
|
97
|
+
/** Accept `gzip, br` response content and auto decode it, default is `true`. */
|
93
98
|
compressed?: boolean;
|
94
99
|
/**
|
95
100
|
* @deprecated
|
@@ -97,11 +102,11 @@ export type RequestOptions = {
|
|
97
102
|
* */
|
98
103
|
gzip?: boolean;
|
99
104
|
/**
|
100
|
-
* Enable timing or not, default is
|
105
|
+
* Enable timing or not, default is `true`.
|
101
106
|
* */
|
102
107
|
timing?: boolean;
|
103
108
|
/**
|
104
|
-
* Auto retry times on 5xx response, default is 0
|
109
|
+
* Auto retry times on 5xx response, default is `0`. Don't work on streaming request
|
105
110
|
* It's not supported by using retry and writeStream, because the retry request can't stop the stream which is consuming.
|
106
111
|
**/
|
107
112
|
retry?: number;
|
@@ -112,6 +117,11 @@ export type RequestOptions = {
|
|
112
117
|
* It will retry when status >= 500 by default. Request error is not included.
|
113
118
|
*/
|
114
119
|
isRetry?: (response: HttpClientResponse) => boolean;
|
120
|
+
/**
|
121
|
+
* Auto retry times on socket error, default is `1`. Don't work on streaming request
|
122
|
+
* It's not supported by using retry and writeStream, because the retry request can't stop the stream which is consuming.
|
123
|
+
**/
|
124
|
+
socketErrorRetry?: number;
|
115
125
|
/** Default: `null` */
|
116
126
|
opaque?: unknown;
|
117
127
|
/**
|
@@ -132,3 +142,10 @@ export type RequestOptions = {
|
|
132
142
|
/** Default: `64 KiB` */
|
133
143
|
highWaterMark?: number;
|
134
144
|
};
|
145
|
+
export type RequestMeta = {
|
146
|
+
requestId: number;
|
147
|
+
url: string;
|
148
|
+
args: RequestOptions;
|
149
|
+
ctx?: unknown;
|
150
|
+
retries: number;
|
151
|
+
};
|
package/src/esm/Response.d.ts
CHANGED
@@ -13,6 +13,8 @@ export type SocketInfo = {
|
|
13
13
|
bytesRead: number;
|
14
14
|
handledRequests: number;
|
15
15
|
handledResponses: number;
|
16
|
+
connectedTime?: Date;
|
17
|
+
lastRequestEndTime?: Date;
|
16
18
|
};
|
17
19
|
/**
|
18
20
|
* https://eggjs.org/en/core/httpclient.html#timing-boolean
|
@@ -37,6 +39,8 @@ export type RawResponseWithMeta = Readable & {
|
|
37
39
|
rt: number;
|
38
40
|
keepAliveSocket: boolean;
|
39
41
|
requestUrls: string[];
|
42
|
+
retries: number;
|
43
|
+
socketErrorRetries: number;
|
40
44
|
};
|
41
45
|
export type HttpClientResponse<T = any> = {
|
42
46
|
opaque: unknown;
|
@@ -15,6 +15,25 @@ let initedDiagnosticsChannel = false;
|
|
15
15
|
// server --> client
|
16
16
|
// undici:request:headers => { request, response }
|
17
17
|
// -> undici:request:trailers => { request, trailers }
|
18
|
+
function subscribe(name, listener) {
|
19
|
+
if (typeof diagnosticsChannel.subscribe === 'function') {
|
20
|
+
diagnosticsChannel.subscribe(name, listener);
|
21
|
+
}
|
22
|
+
else {
|
23
|
+
// TODO: support Node.js 14, will be removed on the next major version
|
24
|
+
diagnosticsChannel.channel(name).subscribe(listener);
|
25
|
+
}
|
26
|
+
}
|
27
|
+
function formatSocket(socket) {
|
28
|
+
if (!socket)
|
29
|
+
return socket;
|
30
|
+
return {
|
31
|
+
localAddress: socket[symbols.kSocketLocalAddress],
|
32
|
+
localPort: socket[symbols.kSocketLocalPort],
|
33
|
+
remoteAddress: socket.remoteAddress,
|
34
|
+
remotePort: socket.remotePort,
|
35
|
+
};
|
36
|
+
}
|
18
37
|
export function initDiagnosticsChannel() {
|
19
38
|
// makre sure init global DiagnosticsChannel once
|
20
39
|
if (initedDiagnosticsChannel)
|
@@ -23,7 +42,7 @@ export function initDiagnosticsChannel() {
|
|
23
42
|
let kHandler;
|
24
43
|
// This message is published when a new outgoing request is created.
|
25
44
|
// Note: a request is only loosely completed to a given socket.
|
26
|
-
|
45
|
+
subscribe('undici:request:create', (message, name) => {
|
27
46
|
const { request } = message;
|
28
47
|
if (!kHandler) {
|
29
48
|
const symbols = Object.getOwnPropertySymbols(request);
|
@@ -46,16 +65,20 @@ export function initDiagnosticsChannel() {
|
|
46
65
|
// diagnosticsChannel.channel('undici:client:beforeConnect')
|
47
66
|
// diagnosticsChannel.channel('undici:client:connectError')
|
48
67
|
// This message is published after a connection is established.
|
49
|
-
|
68
|
+
subscribe('undici:client:connected', (message, name) => {
|
50
69
|
const { socket } = message;
|
51
70
|
socket[symbols.kSocketId] = globalId('UndiciSocket');
|
52
71
|
socket[symbols.kSocketStartTime] = performance.now();
|
72
|
+
socket[symbols.kSocketConnectedTime] = new Date();
|
53
73
|
socket[symbols.kHandledRequests] = 0;
|
54
74
|
socket[symbols.kHandledResponses] = 0;
|
55
|
-
|
75
|
+
// copy local address to symbol, avoid them be reset after request error throw
|
76
|
+
socket[symbols.kSocketLocalAddress] = socket.localAddress;
|
77
|
+
socket[symbols.kSocketLocalPort] = socket.localPort;
|
78
|
+
debug('[%s] Socket#%d connected (sock: %o)', name, socket[symbols.kSocketId], formatSocket(socket));
|
56
79
|
});
|
57
80
|
// This message is published right before the first byte of the request is written to the socket.
|
58
|
-
|
81
|
+
subscribe('undici:client:sendHeaders', (message, name) => {
|
59
82
|
const { request, socket } = message;
|
60
83
|
if (!kHandler)
|
61
84
|
return;
|
@@ -65,7 +88,7 @@ export function initDiagnosticsChannel() {
|
|
65
88
|
socket[symbols.kHandledRequests]++;
|
66
89
|
// attach socket to opaque
|
67
90
|
opaque[symbols.kRequestSocket] = socket;
|
68
|
-
debug('[%s] Request#%d send headers on Socket#%d (handled %d requests)', name, opaque[symbols.kRequestId], socket[symbols.kSocketId], socket[symbols.kHandledRequests]);
|
91
|
+
debug('[%s] Request#%d send headers on Socket#%d (handled %d requests, sock: %o)', name, opaque[symbols.kRequestId], socket[symbols.kSocketId], socket[symbols.kHandledRequests], formatSocket(socket));
|
69
92
|
if (!opaque[symbols.kEnableRequestTiming])
|
70
93
|
return;
|
71
94
|
opaque[symbols.kRequestTiming].requestHeadersSent = performanceTime(opaque[symbols.kRequestStartTime]);
|
@@ -76,7 +99,7 @@ export function initDiagnosticsChannel() {
|
|
76
99
|
performanceTime(opaque[symbols.kRequestStartTime], socket[symbols.kSocketStartTime]);
|
77
100
|
}
|
78
101
|
});
|
79
|
-
|
102
|
+
subscribe('undici:request:bodySent', (message, name) => {
|
80
103
|
const { request } = message;
|
81
104
|
if (!kHandler)
|
82
105
|
return;
|
@@ -89,7 +112,7 @@ export function initDiagnosticsChannel() {
|
|
89
112
|
opaque[symbols.kRequestTiming].requestSent = performanceTime(opaque[symbols.kRequestStartTime]);
|
90
113
|
});
|
91
114
|
// This message is published after the response headers have been received, i.e. the response has been completed.
|
92
|
-
|
115
|
+
subscribe('undici:request:headers', (message, name) => {
|
93
116
|
const { request, response } = message;
|
94
117
|
if (!kHandler)
|
95
118
|
return;
|
@@ -99,13 +122,13 @@ export function initDiagnosticsChannel() {
|
|
99
122
|
// get socket from opaque
|
100
123
|
const socket = opaque[symbols.kRequestSocket];
|
101
124
|
socket[symbols.kHandledResponses]++;
|
102
|
-
debug('[%s] Request#%d get %s response headers on Socket#%d (handled %d responses)', name, opaque[symbols.kRequestId], response.statusCode, socket[symbols.kSocketId], socket[symbols.kHandledResponses]);
|
125
|
+
debug('[%s] Request#%d get %s response headers on Socket#%d (handled %d responses, sock: %o)', name, opaque[symbols.kRequestId], response.statusCode, socket[symbols.kSocketId], socket[symbols.kHandledResponses], formatSocket(socket));
|
103
126
|
if (!opaque[symbols.kEnableRequestTiming])
|
104
127
|
return;
|
105
128
|
opaque[symbols.kRequestTiming].waiting = performanceTime(opaque[symbols.kRequestStartTime]);
|
106
129
|
});
|
107
130
|
// This message is published after the response body and trailers have been received, i.e. the response has been completed.
|
108
|
-
|
131
|
+
subscribe('undici:request:trailers', (message, name) => {
|
109
132
|
const { request } = message;
|
110
133
|
if (!kHandler)
|
111
134
|
return;
|
@@ -117,5 +140,14 @@ export function initDiagnosticsChannel() {
|
|
117
140
|
return;
|
118
141
|
opaque[symbols.kRequestTiming].contentDownload = performanceTime(opaque[symbols.kRequestStartTime]);
|
119
142
|
});
|
120
|
-
//
|
143
|
+
// This message is published if the request is going to error, but it has not errored yet.
|
144
|
+
// subscribe('undici:request:error', (message, name) => {
|
145
|
+
// const { request, error } = message as DiagnosticsChannel.RequestErrorMessage;
|
146
|
+
// const opaque = request[kHandler]?.opts?.opaque;
|
147
|
+
// if (!opaque || !opaque[symbols.kRequestId]) return;
|
148
|
+
// const socket = opaque[symbols.kRequestSocket];
|
149
|
+
// debug('[%s] Request#%d error on Socket#%d (handled %d responses, sock: %o), error: %o',
|
150
|
+
// name, opaque[symbols.kRequestId], socket[symbols.kSocketId], socket[symbols.kHandledResponses],
|
151
|
+
// formatSocket(socket), error);
|
152
|
+
// });
|
121
153
|
}
|
package/src/esm/index.d.ts
CHANGED
@@ -2,7 +2,7 @@ import { RequestOptions, RequestURL } from './Request';
|
|
2
2
|
export declare function request<T = any>(url: RequestURL, options?: RequestOptions): Promise<import("./Response").HttpClientResponse<T>>;
|
3
3
|
export declare function curl<T = any>(url: RequestURL, options?: RequestOptions): Promise<import("./Response").HttpClientResponse<T>>;
|
4
4
|
export { MockAgent, ProxyAgent, Agent, Dispatcher, setGlobalDispatcher, getGlobalDispatcher, } from 'undici';
|
5
|
-
export { HttpClient, HttpClient as HttpClient2, HEADER_USER_AGENT as USER_AGENT } from './HttpClient';
|
5
|
+
export { HttpClient, HttpClient as HttpClient2, HEADER_USER_AGENT as USER_AGENT, RequestDiagnosticsMessage, ResponseDiagnosticsMessage, } from './HttpClient';
|
6
6
|
export { RequestOptions, RequestOptions as RequestOptions2, RequestURL, HttpMethod, FixJSONCtlCharsHandler, FixJSONCtlChars, } from './Request';
|
7
7
|
export { SocketInfo, Timing, RawResponseWithMeta, HttpClientResponse } from './Response';
|
8
8
|
declare const _default: {
|
package/src/esm/index.js
CHANGED
@@ -28,7 +28,7 @@ export async function curl(url, options) {
|
|
28
28
|
}
|
29
29
|
export { MockAgent, ProxyAgent, Agent, Dispatcher, setGlobalDispatcher, getGlobalDispatcher, } from 'undici';
|
30
30
|
// HttpClient2 is keep compatible with urlib@2 HttpClient2
|
31
|
-
export { HttpClient, HttpClient as HttpClient2, HEADER_USER_AGENT as USER_AGENT } from './HttpClient.js';
|
31
|
+
export { HttpClient, HttpClient as HttpClient2, HEADER_USER_AGENT as USER_AGENT, } from './HttpClient.js';
|
32
32
|
export default {
|
33
33
|
request,
|
34
34
|
curl,
|
package/src/esm/symbols.d.ts
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
declare const _default: {
|
2
2
|
kSocketId: symbol;
|
3
3
|
kSocketStartTime: symbol;
|
4
|
+
kSocketConnectedTime: symbol;
|
5
|
+
kSocketRequestEndTime: symbol;
|
6
|
+
kSocketLocalAddress: symbol;
|
7
|
+
kSocketLocalPort: symbol;
|
4
8
|
kHandledRequests: symbol;
|
5
9
|
kHandledResponses: symbol;
|
6
10
|
kRequestSocket: symbol;
|
package/src/esm/symbols.js
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
export default {
|
2
2
|
kSocketId: Symbol('socket id'),
|
3
3
|
kSocketStartTime: Symbol('socket start time'),
|
4
|
+
kSocketConnectedTime: Symbol('socket connected time'),
|
5
|
+
kSocketRequestEndTime: Symbol('socket request end time'),
|
6
|
+
kSocketLocalAddress: Symbol('socket local address'),
|
7
|
+
kSocketLocalPort: Symbol('socket local port'),
|
4
8
|
kHandledRequests: Symbol('handled requests per socket'),
|
5
9
|
kHandledResponses: Symbol('handled responses per socket'),
|
6
10
|
kRequestSocket: Symbol('request on the socket'),
|
package/src/index.ts
CHANGED
@@ -36,7 +36,10 @@ export {
|
|
36
36
|
setGlobalDispatcher, getGlobalDispatcher,
|
37
37
|
} from 'undici';
|
38
38
|
// HttpClient2 is keep compatible with urlib@2 HttpClient2
|
39
|
-
export {
|
39
|
+
export {
|
40
|
+
HttpClient, HttpClient as HttpClient2, HEADER_USER_AGENT as USER_AGENT,
|
41
|
+
RequestDiagnosticsMessage, ResponseDiagnosticsMessage,
|
42
|
+
} from './HttpClient';
|
40
43
|
// RequestOptions2 is keep compatible with urlib@2 RequestOptions2
|
41
44
|
export {
|
42
45
|
RequestOptions, RequestOptions as RequestOptions2, RequestURL, HttpMethod,
|
package/src/symbols.ts
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
export default {
|
2
2
|
kSocketId: Symbol('socket id'),
|
3
3
|
kSocketStartTime: Symbol('socket start time'),
|
4
|
+
kSocketConnectedTime: Symbol('socket connected time'),
|
5
|
+
kSocketRequestEndTime: Symbol('socket request end time'),
|
6
|
+
kSocketLocalAddress: Symbol('socket local address'),
|
7
|
+
kSocketLocalPort: Symbol('socket local port'),
|
4
8
|
kHandledRequests: Symbol('handled requests per socket'),
|
5
9
|
kHandledResponses: Symbol('handled responses per socket'),
|
6
10
|
kRequestSocket: Symbol('request on the socket'),
|