follow-redirects 1.15.1 → 1.15.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.
Potentially problematic release.
This version of follow-redirects might be problematic. Click here for more details.
- package/index.js +64 -29
- package/package.json +2 -3
package/index.js
CHANGED
@@ -15,6 +15,11 @@ events.forEach(function (event) {
|
|
15
15
|
};
|
16
16
|
});
|
17
17
|
|
18
|
+
var InvalidUrlError = createErrorType(
|
19
|
+
"ERR_INVALID_URL",
|
20
|
+
"Invalid URL",
|
21
|
+
TypeError
|
22
|
+
);
|
18
23
|
// Error types with codes
|
19
24
|
var RedirectionError = createErrorType(
|
20
25
|
"ERR_FR_REDIRECTION_FAILURE",
|
@@ -33,6 +38,9 @@ var WriteAfterEndError = createErrorType(
|
|
33
38
|
"write after end"
|
34
39
|
);
|
35
40
|
|
41
|
+
// istanbul ignore next
|
42
|
+
var destroy = Writable.prototype.destroy || noop;
|
43
|
+
|
36
44
|
// An HTTP(S) request that can be redirected
|
37
45
|
function RedirectableRequest(options, responseCallback) {
|
38
46
|
// Initialize the request
|
@@ -63,10 +71,17 @@ function RedirectableRequest(options, responseCallback) {
|
|
63
71
|
RedirectableRequest.prototype = Object.create(Writable.prototype);
|
64
72
|
|
65
73
|
RedirectableRequest.prototype.abort = function () {
|
66
|
-
|
74
|
+
destroyRequest(this._currentRequest);
|
75
|
+
this._currentRequest.abort();
|
67
76
|
this.emit("abort");
|
68
77
|
};
|
69
78
|
|
79
|
+
RedirectableRequest.prototype.destroy = function (error) {
|
80
|
+
destroyRequest(this._currentRequest, error);
|
81
|
+
destroy.call(this, error);
|
82
|
+
return this;
|
83
|
+
};
|
84
|
+
|
70
85
|
// Writes buffered data to the current native request
|
71
86
|
RedirectableRequest.prototype.write = function (data, encoding, callback) {
|
72
87
|
// Writing is not allowed if end has been called
|
@@ -75,10 +90,10 @@ RedirectableRequest.prototype.write = function (data, encoding, callback) {
|
|
75
90
|
}
|
76
91
|
|
77
92
|
// Validate input and shift parameters if necessary
|
78
|
-
if (!(
|
93
|
+
if (!isString(data) && !isBuffer(data)) {
|
79
94
|
throw new TypeError("data should be a string, Buffer or Uint8Array");
|
80
95
|
}
|
81
|
-
if (
|
96
|
+
if (isFunction(encoding)) {
|
82
97
|
callback = encoding;
|
83
98
|
encoding = null;
|
84
99
|
}
|
@@ -107,11 +122,11 @@ RedirectableRequest.prototype.write = function (data, encoding, callback) {
|
|
107
122
|
// Ends the current native request
|
108
123
|
RedirectableRequest.prototype.end = function (data, encoding, callback) {
|
109
124
|
// Shift parameters if necessary
|
110
|
-
if (
|
125
|
+
if (isFunction(data)) {
|
111
126
|
callback = data;
|
112
127
|
data = encoding = null;
|
113
128
|
}
|
114
|
-
else if (
|
129
|
+
else if (isFunction(encoding)) {
|
115
130
|
callback = encoding;
|
116
131
|
encoding = null;
|
117
132
|
}
|
@@ -179,6 +194,7 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
|
|
179
194
|
self.removeListener("abort", clearTimer);
|
180
195
|
self.removeListener("error", clearTimer);
|
181
196
|
self.removeListener("response", clearTimer);
|
197
|
+
self.removeListener("close", clearTimer);
|
182
198
|
if (callback) {
|
183
199
|
self.removeListener("timeout", callback);
|
184
200
|
}
|
@@ -205,6 +221,7 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
|
|
205
221
|
this.on("abort", clearTimer);
|
206
222
|
this.on("error", clearTimer);
|
207
223
|
this.on("response", clearTimer);
|
224
|
+
this.on("close", clearTimer);
|
208
225
|
|
209
226
|
return this;
|
210
227
|
};
|
@@ -288,7 +305,7 @@ RedirectableRequest.prototype._performRequest = function () {
|
|
288
305
|
url.format(this._options) :
|
289
306
|
// When making a request to a proxy, […]
|
290
307
|
// a client MUST send the target URI in absolute-form […].
|
291
|
-
this.
|
308
|
+
this._options.path;
|
292
309
|
|
293
310
|
// End a redirected request
|
294
311
|
// (The first request must be ended explicitly with RedirectableRequest#end)
|
@@ -356,7 +373,7 @@ RedirectableRequest.prototype._processResponse = function (response) {
|
|
356
373
|
}
|
357
374
|
|
358
375
|
// The response is a redirect, so abort the current request
|
359
|
-
|
376
|
+
destroyRequest(this._currentRequest);
|
360
377
|
// Discard the remainder of the response to avoid waiting for data
|
361
378
|
response.destroy();
|
362
379
|
|
@@ -409,7 +426,7 @@ RedirectableRequest.prototype._processResponse = function (response) {
|
|
409
426
|
redirectUrl = url.resolve(currentUrl, location);
|
410
427
|
}
|
411
428
|
catch (cause) {
|
412
|
-
this.emit("error", new RedirectionError(cause));
|
429
|
+
this.emit("error", new RedirectionError({ cause: cause }));
|
413
430
|
return;
|
414
431
|
}
|
415
432
|
|
@@ -429,7 +446,7 @@ RedirectableRequest.prototype._processResponse = function (response) {
|
|
429
446
|
}
|
430
447
|
|
431
448
|
// Evaluate the beforeRedirect callback
|
432
|
-
if (
|
449
|
+
if (isFunction(beforeRedirect)) {
|
433
450
|
var responseDetails = {
|
434
451
|
headers: response.headers,
|
435
452
|
statusCode: statusCode,
|
@@ -454,7 +471,7 @@ RedirectableRequest.prototype._processResponse = function (response) {
|
|
454
471
|
this._performRequest();
|
455
472
|
}
|
456
473
|
catch (cause) {
|
457
|
-
this.emit("error", new RedirectionError(cause));
|
474
|
+
this.emit("error", new RedirectionError({ cause: cause }));
|
458
475
|
}
|
459
476
|
};
|
460
477
|
|
@@ -476,15 +493,19 @@ function wrap(protocols) {
|
|
476
493
|
// Executes a request, following redirects
|
477
494
|
function request(input, options, callback) {
|
478
495
|
// Parse parameters
|
479
|
-
if (
|
480
|
-
var
|
496
|
+
if (isString(input)) {
|
497
|
+
var parsed;
|
481
498
|
try {
|
482
|
-
|
499
|
+
parsed = urlToOptions(new URL(input));
|
483
500
|
}
|
484
501
|
catch (err) {
|
485
502
|
/* istanbul ignore next */
|
486
|
-
|
503
|
+
parsed = url.parse(input);
|
487
504
|
}
|
505
|
+
if (!isString(parsed.protocol)) {
|
506
|
+
throw new InvalidUrlError({ input });
|
507
|
+
}
|
508
|
+
input = parsed;
|
488
509
|
}
|
489
510
|
else if (URL && (input instanceof URL)) {
|
490
511
|
input = urlToOptions(input);
|
@@ -494,7 +515,7 @@ function wrap(protocols) {
|
|
494
515
|
options = input;
|
495
516
|
input = { protocol: protocol };
|
496
517
|
}
|
497
|
-
if (
|
518
|
+
if (isFunction(options)) {
|
498
519
|
callback = options;
|
499
520
|
options = null;
|
500
521
|
}
|
@@ -505,6 +526,9 @@ function wrap(protocols) {
|
|
505
526
|
maxBodyLength: exports.maxBodyLength,
|
506
527
|
}, input, options);
|
507
528
|
options.nativeProtocols = nativeProtocols;
|
529
|
+
if (!isString(options.host) && !isString(options.hostname)) {
|
530
|
+
options.hostname = "::1";
|
531
|
+
}
|
508
532
|
|
509
533
|
assert.equal(options.protocol, protocol, "protocol mismatch");
|
510
534
|
debug("options", options);
|
@@ -562,37 +586,48 @@ function removeMatchingHeaders(regex, headers) {
|
|
562
586
|
undefined : String(lastValue).trim();
|
563
587
|
}
|
564
588
|
|
565
|
-
function createErrorType(code,
|
566
|
-
|
589
|
+
function createErrorType(code, message, baseClass) {
|
590
|
+
// Create constructor
|
591
|
+
function CustomError(properties) {
|
567
592
|
Error.captureStackTrace(this, this.constructor);
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
else {
|
572
|
-
this.message = defaultMessage + ": " + cause.message;
|
573
|
-
this.cause = cause;
|
574
|
-
}
|
593
|
+
Object.assign(this, properties || {});
|
594
|
+
this.code = code;
|
595
|
+
this.message = this.cause ? message + ": " + this.cause.message : message;
|
575
596
|
}
|
576
|
-
|
597
|
+
|
598
|
+
// Attach constructor and set default properties
|
599
|
+
CustomError.prototype = new (baseClass || Error)();
|
577
600
|
CustomError.prototype.constructor = CustomError;
|
578
601
|
CustomError.prototype.name = "Error [" + code + "]";
|
579
|
-
CustomError.prototype.code = code;
|
580
602
|
return CustomError;
|
581
603
|
}
|
582
604
|
|
583
|
-
function
|
605
|
+
function destroyRequest(request, error) {
|
584
606
|
for (var event of events) {
|
585
607
|
request.removeListener(event, eventHandlers[event]);
|
586
608
|
}
|
587
609
|
request.on("error", noop);
|
588
|
-
request.
|
610
|
+
request.destroy(error);
|
589
611
|
}
|
590
612
|
|
591
613
|
function isSubdomain(subdomain, domain) {
|
592
|
-
|
614
|
+
assert(isString(subdomain) && isString(domain));
|
615
|
+
var dot = subdomain.length - domain.length - 1;
|
593
616
|
return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain);
|
594
617
|
}
|
595
618
|
|
619
|
+
function isString(value) {
|
620
|
+
return typeof value === "string" || value instanceof String;
|
621
|
+
}
|
622
|
+
|
623
|
+
function isFunction(value) {
|
624
|
+
return typeof value === "function";
|
625
|
+
}
|
626
|
+
|
627
|
+
function isBuffer(value) {
|
628
|
+
return typeof value === "object" && ("length" in value);
|
629
|
+
}
|
630
|
+
|
596
631
|
// Exports
|
597
632
|
module.exports = wrap({ http: http, https: https });
|
598
633
|
module.exports.wrap = wrap;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "follow-redirects",
|
3
|
-
"version": "1.15.
|
3
|
+
"version": "1.15.3",
|
4
4
|
"description": "HTTP and HTTPS modules that follow redirects.",
|
5
5
|
"license": "MIT",
|
6
6
|
"main": "index.js",
|
@@ -11,9 +11,8 @@
|
|
11
11
|
"node": ">=4.0"
|
12
12
|
},
|
13
13
|
"scripts": {
|
14
|
-
"test": "npm run lint && npm run mocha",
|
15
14
|
"lint": "eslint *.js test",
|
16
|
-
"
|
15
|
+
"test": "nyc mocha"
|
17
16
|
},
|
18
17
|
"repository": {
|
19
18
|
"type": "git",
|