urllib 3.17.2 → 3.18.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "urllib",
3
- "version": "3.17.2",
3
+ "version": "3.18.0",
4
4
  "publishConfig": {
5
5
  "tag": "latest"
6
6
  },
@@ -68,6 +68,7 @@
68
68
  "formstream": "^1.1.1",
69
69
  "mime-types": "^2.1.35",
70
70
  "pump": "^3.0.0",
71
+ "qs": "^6.11.2",
71
72
  "undici": "^5.22.1",
72
73
  "ylru": "^1.3.2"
73
74
  },
@@ -77,6 +78,7 @@
77
78
  "@types/mime-types": "^2.1.1",
78
79
  "@types/node": "^20.2.1",
79
80
  "@types/pump": "^1.1.1",
81
+ "@types/qs": "^6.9.7",
80
82
  "@types/selfsigned": "^2.0.1",
81
83
  "@types/tar-stream": "^2.2.2",
82
84
  "@vitest/coverage-v8": "^0.32.0",
package/src/HttpClient.ts CHANGED
@@ -26,6 +26,7 @@ import { FormData as FormDataNode } from 'formdata-node';
26
26
  import { FormDataEncoder } from 'form-data-encoder';
27
27
  import createUserAgent from 'default-user-agent';
28
28
  import mime from 'mime-types';
29
+ import qs from 'qs';
29
30
  import pump from 'pump';
30
31
  // Compatible with old style formstream
31
32
  import FormStream from 'formstream';
@@ -87,7 +88,7 @@ export type ClientOptions = {
87
88
  rejectUnauthorized?: boolean;
88
89
 
89
90
  /**
90
- * sockePath string | null (optional) - Default: null - An IPC endpoint, either Unix domain socket or Windows named pipe
91
+ * socketPath string | null (optional) - Default: null - An IPC endpoint, either Unix domain socket or Windows named pipe
91
92
  */
92
93
  socketPath?: string | null;
93
94
  },
@@ -244,14 +245,14 @@ export class HttpClient extends EventEmitter {
244
245
  // the response body and trailers have been received
245
246
  contentDownload: 0,
246
247
  };
247
- const orginalOpaque = args.opaque;
248
+ const originalOpaque = args.opaque;
248
249
  // using opaque to diagnostics channel, binding request and socket
249
250
  const internalOpaque = {
250
251
  [symbols.kRequestId]: requestId,
251
252
  [symbols.kRequestStartTime]: requestStartTime,
252
253
  [symbols.kEnableRequestTiming]: !!args.timing,
253
254
  [symbols.kRequestTiming]: timing,
254
- [symbols.kRequestOrginalOpaque]: orginalOpaque,
255
+ [symbols.kRequestOriginalOpaque]: originalOpaque,
255
256
  };
256
257
  const reqMeta = {
257
258
  requestId,
@@ -452,10 +453,17 @@ export class HttpClient extends EventEmitter {
452
453
  || isReadable(args.data);
453
454
  if (isGETOrHEAD) {
454
455
  if (!isStringOrBufferOrReadable) {
455
- for (const field in args.data) {
456
- const fieldValue = args.data[field];
457
- if (fieldValue === undefined) continue;
458
- requestUrl.searchParams.append(field, fieldValue);
456
+ if (args.nestedQuerystring) {
457
+ const querystring = qs.stringify(args.data);
458
+ // reset the requestUrl
459
+ const href = requestUrl.href;
460
+ requestUrl = new URL(href + (href.includes('?') ? '&' : '?') + querystring);
461
+ } else {
462
+ for (const field in args.data) {
463
+ const fieldValue = args.data[field];
464
+ if (fieldValue === undefined) continue;
465
+ requestUrl.searchParams.append(field, fieldValue);
466
+ }
459
467
  }
460
468
  }
461
469
  } else {
@@ -472,7 +480,11 @@ export class HttpClient extends EventEmitter {
472
480
  }
473
481
  } else {
474
482
  headers['content-type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
475
- requestOptions.body = new URLSearchParams(args.data).toString();
483
+ if (args.nestedQuerystring) {
484
+ requestOptions.body = qs.stringify(args.data);
485
+ } else {
486
+ requestOptions.body = new URLSearchParams(args.data).toString();
487
+ }
476
488
  }
477
489
  }
478
490
  }
@@ -582,7 +594,7 @@ export class HttpClient extends EventEmitter {
582
594
  this.#updateSocketInfo(socketInfo, internalOpaque);
583
595
 
584
596
  const clientResponse: HttpClientResponse = {
585
- opaque: orginalOpaque,
597
+ opaque: originalOpaque,
586
598
  data,
587
599
  status: res.status,
588
600
  statusCode: res.status,
@@ -637,7 +649,7 @@ export class HttpClient extends EventEmitter {
637
649
  return await this.#requestInternal(url, options, requestContext);
638
650
  }
639
651
  }
640
- err.opaque = orginalOpaque;
652
+ err.opaque = originalOpaque;
641
653
  err.status = res.status;
642
654
  err.headers = res.headers;
643
655
  err.res = res;
package/src/Request.ts CHANGED
@@ -46,6 +46,11 @@ export type RequestOptions = {
46
46
  * Default is 'buffer'.
47
47
  */
48
48
  dataType?: 'text' | 'html' | 'json' | 'buffer' | 'stream';
49
+ /**
50
+ * urllib default use URLSearchParams to stringify form data which don't support nested object,
51
+ * will use qs instead of URLSearchParams to support nested object by set this option to true.
52
+ */
53
+ nestedQuerystring?: boolean;
49
54
  /**
50
55
  * @deprecated
51
56
  * Only for d.ts keep compatible with urllib@2, don't use it anymore.
@@ -31,7 +31,7 @@ export type ClientOptions = {
31
31
  */
32
32
  rejectUnauthorized?: boolean;
33
33
  /**
34
- * sockePath string | null (optional) - Default: null - An IPC endpoint, either Unix domain socket or Windows named pipe
34
+ * socketPath string | null (optional) - Default: null - An IPC endpoint, either Unix domain socket or Windows named pipe
35
35
  */
36
36
  socketPath?: string | null;
37
37
  };
@@ -21,6 +21,7 @@ const formdata_node_1 = require("formdata-node");
21
21
  const form_data_encoder_1 = require("form-data-encoder");
22
22
  const default_user_agent_1 = __importDefault(require("default-user-agent"));
23
23
  const mime_types_1 = __importDefault(require("mime-types"));
24
+ const qs_1 = __importDefault(require("qs"));
24
25
  const pump_1 = __importDefault(require("pump"));
25
26
  // Compatible with old style formstream
26
27
  const formstream_1 = __importDefault(require("formstream"));
@@ -72,7 +73,7 @@ class HttpClientRequestTimeoutError extends Error {
72
73
  Error.captureStackTrace(this, this.constructor);
73
74
  }
74
75
  }
75
- exports.HEADER_USER_AGENT = (0, default_user_agent_1.default)('node-urllib', '3.17.2');
76
+ exports.HEADER_USER_AGENT = (0, default_user_agent_1.default)('node-urllib', '3.18.0');
76
77
  function getFileName(stream) {
77
78
  const filePath = stream.path;
78
79
  if (filePath) {
@@ -167,14 +168,14 @@ class HttpClient extends node_events_1.EventEmitter {
167
168
  // the response body and trailers have been received
168
169
  contentDownload: 0,
169
170
  };
170
- const orginalOpaque = args.opaque;
171
+ const originalOpaque = args.opaque;
171
172
  // using opaque to diagnostics channel, binding request and socket
172
173
  const internalOpaque = {
173
174
  [symbols_1.default.kRequestId]: requestId,
174
175
  [symbols_1.default.kRequestStartTime]: requestStartTime,
175
176
  [symbols_1.default.kEnableRequestTiming]: !!args.timing,
176
177
  [symbols_1.default.kRequestTiming]: timing,
177
- [symbols_1.default.kRequestOrginalOpaque]: orginalOpaque,
178
+ [symbols_1.default.kRequestOriginalOpaque]: originalOpaque,
178
179
  };
179
180
  const reqMeta = {
180
181
  requestId,
@@ -381,11 +382,19 @@ class HttpClient extends node_events_1.EventEmitter {
381
382
  || (0, utils_1.isReadable)(args.data);
382
383
  if (isGETOrHEAD) {
383
384
  if (!isStringOrBufferOrReadable) {
384
- for (const field in args.data) {
385
- const fieldValue = args.data[field];
386
- if (fieldValue === undefined)
387
- continue;
388
- requestUrl.searchParams.append(field, fieldValue);
385
+ if (args.nestedQuerystring) {
386
+ const querystring = qs_1.default.stringify(args.data);
387
+ // reset the requestUrl
388
+ const href = requestUrl.href;
389
+ requestUrl = new URL(href + (href.includes('?') ? '&' : '?') + querystring);
390
+ }
391
+ else {
392
+ for (const field in args.data) {
393
+ const fieldValue = args.data[field];
394
+ if (fieldValue === undefined)
395
+ continue;
396
+ requestUrl.searchParams.append(field, fieldValue);
397
+ }
389
398
  }
390
399
  }
391
400
  }
@@ -405,7 +414,12 @@ class HttpClient extends node_events_1.EventEmitter {
405
414
  }
406
415
  else {
407
416
  headers['content-type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
408
- requestOptions.body = new URLSearchParams(args.data).toString();
417
+ if (args.nestedQuerystring) {
418
+ requestOptions.body = qs_1.default.stringify(args.data);
419
+ }
420
+ else {
421
+ requestOptions.body = new URLSearchParams(args.data).toString();
422
+ }
409
423
  }
410
424
  }
411
425
  }
@@ -515,7 +529,7 @@ class HttpClient extends node_events_1.EventEmitter {
515
529
  // get real socket info from internalOpaque
516
530
  this.#updateSocketInfo(socketInfo, internalOpaque);
517
531
  const clientResponse = {
518
- opaque: orginalOpaque,
532
+ opaque: originalOpaque,
519
533
  data,
520
534
  status: res.status,
521
535
  statusCode: res.status,
@@ -570,7 +584,7 @@ class HttpClient extends node_events_1.EventEmitter {
570
584
  return await this.#requestInternal(url, options, requestContext);
571
585
  }
572
586
  }
573
- err.opaque = orginalOpaque;
587
+ err.opaque = originalOpaque;
574
588
  err.status = res.status;
575
589
  err.headers = res.headers;
576
590
  err.res = res;
@@ -44,6 +44,11 @@ export type RequestOptions = {
44
44
  * Default is 'buffer'.
45
45
  */
46
46
  dataType?: 'text' | 'html' | 'json' | 'buffer' | 'stream';
47
+ /**
48
+ * urllib default use URLSearchParams to stringify form data which don't support nested object,
49
+ * will use qs instead of URLSearchParams to support nested object by set this option to true.
50
+ */
51
+ nestedQuerystring?: boolean;
47
52
  /**
48
53
  * @deprecated
49
54
  * Only for d.ts keep compatible with urllib@2, don't use it anymore.
@@ -12,6 +12,6 @@ declare const _default: {
12
12
  kRequestStartTime: symbol;
13
13
  kEnableRequestTiming: symbol;
14
14
  kRequestTiming: symbol;
15
- kRequestOrginalOpaque: symbol;
15
+ kRequestOriginalOpaque: symbol;
16
16
  };
17
17
  export default _default;
@@ -14,5 +14,5 @@ exports.default = {
14
14
  kRequestStartTime: Symbol('request start time'),
15
15
  kEnableRequestTiming: Symbol('enable request timing or not'),
16
16
  kRequestTiming: Symbol('request timing'),
17
- kRequestOrginalOpaque: Symbol('request orginal opaque'),
17
+ kRequestOriginalOpaque: Symbol('request original opaque'),
18
18
  };
@@ -31,7 +31,7 @@ export type ClientOptions = {
31
31
  */
32
32
  rejectUnauthorized?: boolean;
33
33
  /**
34
- * sockePath string | null (optional) - Default: null - An IPC endpoint, either Unix domain socket or Windows named pipe
34
+ * socketPath string | null (optional) - Default: null - An IPC endpoint, either Unix domain socket or Windows named pipe
35
35
  */
36
36
  socketPath?: string | null;
37
37
  };
@@ -15,6 +15,7 @@ import { FormData as FormDataNode } from 'formdata-node';
15
15
  import { FormDataEncoder } from 'form-data-encoder';
16
16
  import createUserAgent from 'default-user-agent';
17
17
  import mime from 'mime-types';
18
+ import qs from 'qs';
18
19
  import pump from 'pump';
19
20
  // Compatible with old style formstream
20
21
  import FormStream from 'formstream';
@@ -66,7 +67,7 @@ class HttpClientRequestTimeoutError extends Error {
66
67
  Error.captureStackTrace(this, this.constructor);
67
68
  }
68
69
  }
69
- export const HEADER_USER_AGENT = createUserAgent('node-urllib', '3.17.2');
70
+ export const HEADER_USER_AGENT = createUserAgent('node-urllib', '3.18.0');
70
71
  function getFileName(stream) {
71
72
  const filePath = stream.path;
72
73
  if (filePath) {
@@ -161,14 +162,14 @@ export class HttpClient extends EventEmitter {
161
162
  // the response body and trailers have been received
162
163
  contentDownload: 0,
163
164
  };
164
- const orginalOpaque = args.opaque;
165
+ const originalOpaque = args.opaque;
165
166
  // using opaque to diagnostics channel, binding request and socket
166
167
  const internalOpaque = {
167
168
  [symbols.kRequestId]: requestId,
168
169
  [symbols.kRequestStartTime]: requestStartTime,
169
170
  [symbols.kEnableRequestTiming]: !!args.timing,
170
171
  [symbols.kRequestTiming]: timing,
171
- [symbols.kRequestOrginalOpaque]: orginalOpaque,
172
+ [symbols.kRequestOriginalOpaque]: originalOpaque,
172
173
  };
173
174
  const reqMeta = {
174
175
  requestId,
@@ -375,11 +376,19 @@ export class HttpClient extends EventEmitter {
375
376
  || isReadable(args.data);
376
377
  if (isGETOrHEAD) {
377
378
  if (!isStringOrBufferOrReadable) {
378
- for (const field in args.data) {
379
- const fieldValue = args.data[field];
380
- if (fieldValue === undefined)
381
- continue;
382
- requestUrl.searchParams.append(field, fieldValue);
379
+ if (args.nestedQuerystring) {
380
+ const querystring = qs.stringify(args.data);
381
+ // reset the requestUrl
382
+ const href = requestUrl.href;
383
+ requestUrl = new URL(href + (href.includes('?') ? '&' : '?') + querystring);
384
+ }
385
+ else {
386
+ for (const field in args.data) {
387
+ const fieldValue = args.data[field];
388
+ if (fieldValue === undefined)
389
+ continue;
390
+ requestUrl.searchParams.append(field, fieldValue);
391
+ }
383
392
  }
384
393
  }
385
394
  }
@@ -399,7 +408,12 @@ export class HttpClient extends EventEmitter {
399
408
  }
400
409
  else {
401
410
  headers['content-type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
402
- requestOptions.body = new URLSearchParams(args.data).toString();
411
+ if (args.nestedQuerystring) {
412
+ requestOptions.body = qs.stringify(args.data);
413
+ }
414
+ else {
415
+ requestOptions.body = new URLSearchParams(args.data).toString();
416
+ }
403
417
  }
404
418
  }
405
419
  }
@@ -509,7 +523,7 @@ export class HttpClient extends EventEmitter {
509
523
  // get real socket info from internalOpaque
510
524
  this.#updateSocketInfo(socketInfo, internalOpaque);
511
525
  const clientResponse = {
512
- opaque: orginalOpaque,
526
+ opaque: originalOpaque,
513
527
  data,
514
528
  status: res.status,
515
529
  statusCode: res.status,
@@ -564,7 +578,7 @@ export class HttpClient extends EventEmitter {
564
578
  return await this.#requestInternal(url, options, requestContext);
565
579
  }
566
580
  }
567
- err.opaque = orginalOpaque;
581
+ err.opaque = originalOpaque;
568
582
  err.status = res.status;
569
583
  err.headers = res.headers;
570
584
  err.res = res;
@@ -44,6 +44,11 @@ export type RequestOptions = {
44
44
  * Default is 'buffer'.
45
45
  */
46
46
  dataType?: 'text' | 'html' | 'json' | 'buffer' | 'stream';
47
+ /**
48
+ * urllib default use URLSearchParams to stringify form data which don't support nested object,
49
+ * will use qs instead of URLSearchParams to support nested object by set this option to true.
50
+ */
51
+ nestedQuerystring?: boolean;
47
52
  /**
48
53
  * @deprecated
49
54
  * Only for d.ts keep compatible with urllib@2, don't use it anymore.
@@ -12,6 +12,6 @@ declare const _default: {
12
12
  kRequestStartTime: symbol;
13
13
  kEnableRequestTiming: symbol;
14
14
  kRequestTiming: symbol;
15
- kRequestOrginalOpaque: symbol;
15
+ kRequestOriginalOpaque: symbol;
16
16
  };
17
17
  export default _default;
@@ -12,5 +12,5 @@ export default {
12
12
  kRequestStartTime: Symbol('request start time'),
13
13
  kEnableRequestTiming: Symbol('enable request timing or not'),
14
14
  kRequestTiming: Symbol('request timing'),
15
- kRequestOrginalOpaque: Symbol('request orginal opaque'),
15
+ kRequestOriginalOpaque: Symbol('request original opaque'),
16
16
  };
package/src/symbols.ts CHANGED
@@ -12,5 +12,5 @@ export default {
12
12
  kRequestStartTime: Symbol('request start time'),
13
13
  kEnableRequestTiming: Symbol('enable request timing or not'),
14
14
  kRequestTiming: Symbol('request timing'),
15
- kRequestOrginalOpaque: Symbol('request orginal opaque'),
15
+ kRequestOriginalOpaque: Symbol('request original opaque'),
16
16
  };