urllib 3.22.1 → 3.22.3
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/dist/commonjs/HttpClient.js +8 -11
- package/dist/commonjs/diagnosticsChannel.js +20 -13
- package/dist/esm/HttpClient.js +8 -11
- package/dist/esm/diagnosticsChannel.js +20 -13
- package/package.json +2 -2
- package/src/HttpClient.ts +7 -9
- package/src/diagnosticsChannel.ts +20 -9
package/README.md
CHANGED
@@ -68,7 +68,7 @@ console.log('status: %s, body size: %d, headers: %j', res.status, data.length, r
|
|
68
68
|
- **keepAliveTimeout** `number | null` - Default is `4000`, 4 seconds - The timeout after which a socket without active requests will time out. Monitors time between activity on a connected socket. 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.
|
69
69
|
- ***auth*** String - `username:password` used in HTTP Basic Authorization.
|
70
70
|
- ***digestAuth*** String - `username:password` used in HTTP [Digest Authorization](https://en.wikipedia.org/wiki/Digest_access_authentication).
|
71
|
-
- ***followRedirect*** Boolean - follow HTTP 3xx responses as redirects. defaults to
|
71
|
+
- ***followRedirect*** Boolean - follow HTTP 3xx responses as redirects. defaults to true.
|
72
72
|
- ***maxRedirects*** Number - The maximum number of redirects to follow, defaults to 10.
|
73
73
|
- ***formatRedirectUrl*** Function - Format the redirect url by your self. Default is `url.resolve(from, to)`.
|
74
74
|
- ***beforeRequest*** Function - Before request hook, you can change every thing here.
|
@@ -16,6 +16,7 @@ const node_path_1 = require("node:path");
|
|
16
16
|
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
|
+
const node_querystring_1 = __importDefault(require("node:querystring"));
|
19
20
|
const undici_1 = require("undici");
|
20
21
|
const symbols_js_1 = __importDefault(require("undici/lib/core/symbols.js"));
|
21
22
|
const formdata_node_1 = require("formdata-node");
|
@@ -67,7 +68,7 @@ class BlobFromStream {
|
|
67
68
|
return 'Blob';
|
68
69
|
}
|
69
70
|
}
|
70
|
-
exports.HEADER_USER_AGENT = (0, default_user_agent_1.default)('node-urllib', '3.22.
|
71
|
+
exports.HEADER_USER_AGENT = (0, default_user_agent_1.default)('node-urllib', '3.22.3');
|
71
72
|
function getFileName(stream) {
|
72
73
|
const filePath = stream.path;
|
73
74
|
if (filePath) {
|
@@ -412,20 +413,16 @@ class HttpClient extends node_events_1.EventEmitter {
|
|
412
413
|
|| (0, utils_js_1.isReadable)(args.data);
|
413
414
|
if (isGETOrHEAD) {
|
414
415
|
if (!isStringOrBufferOrReadable) {
|
416
|
+
let query;
|
415
417
|
if (args.nestedQuerystring) {
|
416
|
-
|
417
|
-
// reset the requestUrl
|
418
|
-
const href = requestUrl.href;
|
419
|
-
requestUrl = new URL(href + (href.includes('?') ? '&' : '?') + querystring);
|
418
|
+
query = qs_1.default.stringify(args.data);
|
420
419
|
}
|
421
420
|
else {
|
422
|
-
|
423
|
-
const fieldValue = args.data[field];
|
424
|
-
if (fieldValue === undefined)
|
425
|
-
continue;
|
426
|
-
requestUrl.searchParams.append(field, fieldValue);
|
427
|
-
}
|
421
|
+
query = node_querystring_1.default.stringify(args.data);
|
428
422
|
}
|
423
|
+
// reset the requestUrl
|
424
|
+
const href = requestUrl.href;
|
425
|
+
requestUrl = new URL(href + (href.includes('?') ? '&' : '?') + query);
|
429
426
|
}
|
430
427
|
}
|
431
428
|
else {
|
@@ -56,6 +56,21 @@ node_net_1.Socket.prototype.destroy = function (err) {
|
|
56
56
|
}
|
57
57
|
return this[kDestroy](err);
|
58
58
|
};
|
59
|
+
function getRequestOpaque(request, kHandler) {
|
60
|
+
if (!kHandler)
|
61
|
+
return;
|
62
|
+
const handler = request[kHandler];
|
63
|
+
// maxRedirects = 0 will get [Symbol(handler)]: RequestHandler {
|
64
|
+
// responseHeaders: null,
|
65
|
+
// opaque: {
|
66
|
+
// [Symbol(request id)]: 1,
|
67
|
+
// [Symbol(request start time)]: 465.0712921619415,
|
68
|
+
// [Symbol(enable request timing or not)]: true,
|
69
|
+
// [Symbol(request timing)]: [Object],
|
70
|
+
// [Symbol(request original opaque)]: undefined
|
71
|
+
// }
|
72
|
+
return handler?.opts?.opaque ?? handler?.opaque;
|
73
|
+
}
|
59
74
|
function initDiagnosticsChannel() {
|
60
75
|
// makre sure init global DiagnosticsChannel once
|
61
76
|
if (initedDiagnosticsChannel)
|
@@ -75,7 +90,7 @@ function initDiagnosticsChannel() {
|
|
75
90
|
}
|
76
91
|
}
|
77
92
|
}
|
78
|
-
const opaque = request
|
93
|
+
const opaque = getRequestOpaque(request, kHandler);
|
79
94
|
// ignore non HttpClient Request
|
80
95
|
if (!opaque || !opaque[symbols_js_1.default.kRequestId])
|
81
96
|
return;
|
@@ -129,9 +144,7 @@ function initDiagnosticsChannel() {
|
|
129
144
|
// This message is published right before the first byte of the request is written to the socket.
|
130
145
|
subscribe('undici:client:sendHeaders', (message, name) => {
|
131
146
|
const { request, socket } = message;
|
132
|
-
|
133
|
-
return;
|
134
|
-
const opaque = request[kHandler]?.opts?.opaque;
|
147
|
+
const opaque = getRequestOpaque(request, kHandler);
|
135
148
|
if (!opaque || !opaque[symbols_js_1.default.kRequestId])
|
136
149
|
return;
|
137
150
|
socket[symbols_js_1.default.kHandledRequests]++;
|
@@ -150,9 +163,7 @@ function initDiagnosticsChannel() {
|
|
150
163
|
});
|
151
164
|
subscribe('undici:request:bodySent', (message, name) => {
|
152
165
|
const { request } = message;
|
153
|
-
|
154
|
-
return;
|
155
|
-
const opaque = request[kHandler]?.opts?.opaque;
|
166
|
+
const opaque = getRequestOpaque(request, kHandler);
|
156
167
|
if (!opaque || !opaque[symbols_js_1.default.kRequestId])
|
157
168
|
return;
|
158
169
|
debug('[%s] Request#%d send body', name, opaque[symbols_js_1.default.kRequestId]);
|
@@ -163,9 +174,7 @@ function initDiagnosticsChannel() {
|
|
163
174
|
// This message is published after the response headers have been received, i.e. the response has been completed.
|
164
175
|
subscribe('undici:request:headers', (message, name) => {
|
165
176
|
const { request, response } = message;
|
166
|
-
|
167
|
-
return;
|
168
|
-
const opaque = request[kHandler]?.opts?.opaque;
|
177
|
+
const opaque = getRequestOpaque(request, kHandler);
|
169
178
|
if (!opaque || !opaque[symbols_js_1.default.kRequestId])
|
170
179
|
return;
|
171
180
|
// get socket from opaque
|
@@ -179,9 +188,7 @@ function initDiagnosticsChannel() {
|
|
179
188
|
// This message is published after the response body and trailers have been received, i.e. the response has been completed.
|
180
189
|
subscribe('undici:request:trailers', (message, name) => {
|
181
190
|
const { request } = message;
|
182
|
-
|
183
|
-
return;
|
184
|
-
const opaque = request[kHandler]?.opts?.opaque;
|
191
|
+
const opaque = getRequestOpaque(request, kHandler);
|
185
192
|
if (!opaque || !opaque[symbols_js_1.default.kRequestId])
|
186
193
|
return;
|
187
194
|
debug('[%s] Request#%d get response body and trailers', name, opaque[symbols_js_1.default.kRequestId]);
|
package/dist/esm/HttpClient.js
CHANGED
@@ -10,6 +10,7 @@ import { basename } from 'node:path';
|
|
10
10
|
import { createReadStream } from 'node:fs';
|
11
11
|
import { format as urlFormat } from 'node:url';
|
12
12
|
import { performance } from 'node:perf_hooks';
|
13
|
+
import querystring from 'node:querystring';
|
13
14
|
import { FormData as FormDataNative, request as undiciRequest, Agent, getGlobalDispatcher, } from 'undici';
|
14
15
|
import undiciSymbols from 'undici/lib/core/symbols.js';
|
15
16
|
import { FormData as FormDataNode } from 'formdata-node';
|
@@ -61,7 +62,7 @@ class BlobFromStream {
|
|
61
62
|
return 'Blob';
|
62
63
|
}
|
63
64
|
}
|
64
|
-
export const HEADER_USER_AGENT = createUserAgent('node-urllib', '3.22.
|
65
|
+
export const HEADER_USER_AGENT = createUserAgent('node-urllib', '3.22.3');
|
65
66
|
function getFileName(stream) {
|
66
67
|
const filePath = stream.path;
|
67
68
|
if (filePath) {
|
@@ -406,20 +407,16 @@ export class HttpClient extends EventEmitter {
|
|
406
407
|
|| isReadable(args.data);
|
407
408
|
if (isGETOrHEAD) {
|
408
409
|
if (!isStringOrBufferOrReadable) {
|
410
|
+
let query;
|
409
411
|
if (args.nestedQuerystring) {
|
410
|
-
|
411
|
-
// reset the requestUrl
|
412
|
-
const href = requestUrl.href;
|
413
|
-
requestUrl = new URL(href + (href.includes('?') ? '&' : '?') + querystring);
|
412
|
+
query = qs.stringify(args.data);
|
414
413
|
}
|
415
414
|
else {
|
416
|
-
|
417
|
-
const fieldValue = args.data[field];
|
418
|
-
if (fieldValue === undefined)
|
419
|
-
continue;
|
420
|
-
requestUrl.searchParams.append(field, fieldValue);
|
421
|
-
}
|
415
|
+
query = querystring.stringify(args.data);
|
422
416
|
}
|
417
|
+
// reset the requestUrl
|
418
|
+
const href = requestUrl.href;
|
419
|
+
requestUrl = new URL(href + (href.includes('?') ? '&' : '?') + query);
|
423
420
|
}
|
424
421
|
}
|
425
422
|
else {
|
@@ -50,6 +50,21 @@ Socket.prototype.destroy = function (err) {
|
|
50
50
|
}
|
51
51
|
return this[kDestroy](err);
|
52
52
|
};
|
53
|
+
function getRequestOpaque(request, kHandler) {
|
54
|
+
if (!kHandler)
|
55
|
+
return;
|
56
|
+
const handler = request[kHandler];
|
57
|
+
// maxRedirects = 0 will get [Symbol(handler)]: RequestHandler {
|
58
|
+
// responseHeaders: null,
|
59
|
+
// opaque: {
|
60
|
+
// [Symbol(request id)]: 1,
|
61
|
+
// [Symbol(request start time)]: 465.0712921619415,
|
62
|
+
// [Symbol(enable request timing or not)]: true,
|
63
|
+
// [Symbol(request timing)]: [Object],
|
64
|
+
// [Symbol(request original opaque)]: undefined
|
65
|
+
// }
|
66
|
+
return handler?.opts?.opaque ?? handler?.opaque;
|
67
|
+
}
|
53
68
|
export function initDiagnosticsChannel() {
|
54
69
|
// makre sure init global DiagnosticsChannel once
|
55
70
|
if (initedDiagnosticsChannel)
|
@@ -69,7 +84,7 @@ export function initDiagnosticsChannel() {
|
|
69
84
|
}
|
70
85
|
}
|
71
86
|
}
|
72
|
-
const opaque = request
|
87
|
+
const opaque = getRequestOpaque(request, kHandler);
|
73
88
|
// ignore non HttpClient Request
|
74
89
|
if (!opaque || !opaque[symbols.kRequestId])
|
75
90
|
return;
|
@@ -123,9 +138,7 @@ export function initDiagnosticsChannel() {
|
|
123
138
|
// This message is published right before the first byte of the request is written to the socket.
|
124
139
|
subscribe('undici:client:sendHeaders', (message, name) => {
|
125
140
|
const { request, socket } = message;
|
126
|
-
|
127
|
-
return;
|
128
|
-
const opaque = request[kHandler]?.opts?.opaque;
|
141
|
+
const opaque = getRequestOpaque(request, kHandler);
|
129
142
|
if (!opaque || !opaque[symbols.kRequestId])
|
130
143
|
return;
|
131
144
|
socket[symbols.kHandledRequests]++;
|
@@ -144,9 +157,7 @@ export function initDiagnosticsChannel() {
|
|
144
157
|
});
|
145
158
|
subscribe('undici:request:bodySent', (message, name) => {
|
146
159
|
const { request } = message;
|
147
|
-
|
148
|
-
return;
|
149
|
-
const opaque = request[kHandler]?.opts?.opaque;
|
160
|
+
const opaque = getRequestOpaque(request, kHandler);
|
150
161
|
if (!opaque || !opaque[symbols.kRequestId])
|
151
162
|
return;
|
152
163
|
debug('[%s] Request#%d send body', name, opaque[symbols.kRequestId]);
|
@@ -157,9 +168,7 @@ export function initDiagnosticsChannel() {
|
|
157
168
|
// This message is published after the response headers have been received, i.e. the response has been completed.
|
158
169
|
subscribe('undici:request:headers', (message, name) => {
|
159
170
|
const { request, response } = message;
|
160
|
-
|
161
|
-
return;
|
162
|
-
const opaque = request[kHandler]?.opts?.opaque;
|
171
|
+
const opaque = getRequestOpaque(request, kHandler);
|
163
172
|
if (!opaque || !opaque[symbols.kRequestId])
|
164
173
|
return;
|
165
174
|
// get socket from opaque
|
@@ -173,9 +182,7 @@ export function initDiagnosticsChannel() {
|
|
173
182
|
// This message is published after the response body and trailers have been received, i.e. the response has been completed.
|
174
183
|
subscribe('undici:request:trailers', (message, name) => {
|
175
184
|
const { request } = message;
|
176
|
-
|
177
|
-
return;
|
178
|
-
const opaque = request[kHandler]?.opts?.opaque;
|
185
|
+
const opaque = getRequestOpaque(request, kHandler);
|
179
186
|
if (!opaque || !opaque[symbols.kRequestId])
|
180
187
|
return;
|
181
188
|
debug('[%s] Request#%d get response body and trailers', name, opaque[symbols.kRequestId]);
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "urllib",
|
3
|
-
"version": "3.22.
|
3
|
+
"version": "3.22.3",
|
4
4
|
"publishConfig": {
|
5
5
|
"tag": "latest"
|
6
6
|
},
|
@@ -55,7 +55,7 @@
|
|
55
55
|
"pump": "^3.0.0",
|
56
56
|
"qs": "^6.11.2",
|
57
57
|
"type-fest": "^4.3.1",
|
58
|
-
"undici": "^5.
|
58
|
+
"undici": "^5.28.2",
|
59
59
|
"ylru": "^1.3.2"
|
60
60
|
},
|
61
61
|
"devDependencies": {
|
package/src/HttpClient.ts
CHANGED
@@ -16,6 +16,7 @@ import { basename } from 'node:path';
|
|
16
16
|
import { createReadStream } from 'node:fs';
|
17
17
|
import { format as urlFormat } from 'node:url';
|
18
18
|
import { performance } from 'node:perf_hooks';
|
19
|
+
import querystring from 'node:querystring';
|
19
20
|
import {
|
20
21
|
FormData as FormDataNative,
|
21
22
|
request as undiciRequest,
|
@@ -503,18 +504,15 @@ export class HttpClient extends EventEmitter {
|
|
503
504
|
|| isReadable(args.data);
|
504
505
|
if (isGETOrHEAD) {
|
505
506
|
if (!isStringOrBufferOrReadable) {
|
507
|
+
let query;
|
506
508
|
if (args.nestedQuerystring) {
|
507
|
-
|
508
|
-
// reset the requestUrl
|
509
|
-
const href = requestUrl.href;
|
510
|
-
requestUrl = new URL(href + (href.includes('?') ? '&' : '?') + querystring);
|
509
|
+
query = qs.stringify(args.data);
|
511
510
|
} else {
|
512
|
-
|
513
|
-
const fieldValue = args.data[field];
|
514
|
-
if (fieldValue === undefined) continue;
|
515
|
-
requestUrl.searchParams.append(field, fieldValue);
|
516
|
-
}
|
511
|
+
query = querystring.stringify(args.data);
|
517
512
|
}
|
513
|
+
// reset the requestUrl
|
514
|
+
const href = requestUrl.href;
|
515
|
+
requestUrl = new URL(href + (href.includes('?') ? '&' : '?') + query);
|
518
516
|
}
|
519
517
|
} else {
|
520
518
|
if (isStringOrBufferOrReadable) {
|
@@ -54,6 +54,21 @@ Socket.prototype.destroy = function(err?: any) {
|
|
54
54
|
return this[kDestroy](err);
|
55
55
|
};
|
56
56
|
|
57
|
+
function getRequestOpaque(request: DiagnosticsChannel.Request, kHandler?: symbol) {
|
58
|
+
if (!kHandler) return;
|
59
|
+
const handler = request[kHandler];
|
60
|
+
// maxRedirects = 0 will get [Symbol(handler)]: RequestHandler {
|
61
|
+
// responseHeaders: null,
|
62
|
+
// opaque: {
|
63
|
+
// [Symbol(request id)]: 1,
|
64
|
+
// [Symbol(request start time)]: 465.0712921619415,
|
65
|
+
// [Symbol(enable request timing or not)]: true,
|
66
|
+
// [Symbol(request timing)]: [Object],
|
67
|
+
// [Symbol(request original opaque)]: undefined
|
68
|
+
// }
|
69
|
+
return handler?.opts?.opaque ?? handler?.opaque;
|
70
|
+
}
|
71
|
+
|
57
72
|
export function initDiagnosticsChannel() {
|
58
73
|
// makre sure init global DiagnosticsChannel once
|
59
74
|
if (initedDiagnosticsChannel) return;
|
@@ -73,7 +88,7 @@ export function initDiagnosticsChannel() {
|
|
73
88
|
}
|
74
89
|
}
|
75
90
|
}
|
76
|
-
const opaque = request
|
91
|
+
const opaque = getRequestOpaque(request, kHandler);
|
77
92
|
// ignore non HttpClient Request
|
78
93
|
if (!opaque || !opaque[symbols.kRequestId]) return;
|
79
94
|
debug('[%s] Request#%d %s %s, path: %s, headers: %o',
|
@@ -131,8 +146,7 @@ export function initDiagnosticsChannel() {
|
|
131
146
|
// This message is published right before the first byte of the request is written to the socket.
|
132
147
|
subscribe('undici:client:sendHeaders', (message, name) => {
|
133
148
|
const { request, socket } = message as DiagnosticsChannel.ClientSendHeadersMessage;
|
134
|
-
|
135
|
-
const opaque = request[kHandler]?.opts?.opaque;
|
149
|
+
const opaque = getRequestOpaque(request, kHandler);
|
136
150
|
if (!opaque || !opaque[symbols.kRequestId]) return;
|
137
151
|
|
138
152
|
socket[symbols.kHandledRequests]++;
|
@@ -154,8 +168,7 @@ export function initDiagnosticsChannel() {
|
|
154
168
|
|
155
169
|
subscribe('undici:request:bodySent', (message, name) => {
|
156
170
|
const { request } = message as DiagnosticsChannel.RequestBodySentMessage;
|
157
|
-
|
158
|
-
const opaque = request[kHandler]?.opts?.opaque;
|
171
|
+
const opaque = getRequestOpaque(request, kHandler);
|
159
172
|
if (!opaque || !opaque[symbols.kRequestId]) return;
|
160
173
|
|
161
174
|
debug('[%s] Request#%d send body', name, opaque[symbols.kRequestId]);
|
@@ -166,8 +179,7 @@ export function initDiagnosticsChannel() {
|
|
166
179
|
// This message is published after the response headers have been received, i.e. the response has been completed.
|
167
180
|
subscribe('undici:request:headers', (message, name) => {
|
168
181
|
const { request, response } = message as DiagnosticsChannel.RequestHeadersMessage;
|
169
|
-
|
170
|
-
const opaque = request[kHandler]?.opts?.opaque;
|
182
|
+
const opaque = getRequestOpaque(request, kHandler);
|
171
183
|
if (!opaque || !opaque[symbols.kRequestId]) return;
|
172
184
|
|
173
185
|
// get socket from opaque
|
@@ -184,8 +196,7 @@ export function initDiagnosticsChannel() {
|
|
184
196
|
// This message is published after the response body and trailers have been received, i.e. the response has been completed.
|
185
197
|
subscribe('undici:request:trailers', (message, name) => {
|
186
198
|
const { request } = message as DiagnosticsChannel.RequestTrailersMessage;
|
187
|
-
|
188
|
-
const opaque = request[kHandler]?.opts?.opaque;
|
199
|
+
const opaque = getRequestOpaque(request, kHandler);
|
189
200
|
if (!opaque || !opaque[symbols.kRequestId]) return;
|
190
201
|
|
191
202
|
debug('[%s] Request#%d get response body and trailers', name, opaque[symbols.kRequestId]);
|