follow-redirects 1.14.1 → 1.14.5
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/debug.js +2 -1
- package/index.js +58 -21
- package/package.json +1 -1
package/debug.js
CHANGED
package/index.js
CHANGED
@@ -18,7 +18,7 @@ events.forEach(function (event) {
|
|
18
18
|
// Error types with codes
|
19
19
|
var RedirectionError = createErrorType(
|
20
20
|
"ERR_FR_REDIRECTION_FAILURE",
|
21
|
-
""
|
21
|
+
"Redirected request failed"
|
22
22
|
);
|
23
23
|
var TooManyRedirectsError = createErrorType(
|
24
24
|
"ERR_FR_TOO_MANY_REDIRECTS",
|
@@ -147,10 +147,8 @@ RedirectableRequest.prototype.removeHeader = function (name) {
|
|
147
147
|
// Global timeout for all underlying requests
|
148
148
|
RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
|
149
149
|
var self = this;
|
150
|
-
if (callback) {
|
151
|
-
this.on("timeout", callback);
|
152
|
-
}
|
153
150
|
|
151
|
+
// Destroys the socket on timeout
|
154
152
|
function destroyOnTimeout(socket) {
|
155
153
|
socket.setTimeout(msecs);
|
156
154
|
socket.removeListener("timeout", socket.destroy);
|
@@ -169,18 +167,32 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
|
|
169
167
|
destroyOnTimeout(socket);
|
170
168
|
}
|
171
169
|
|
172
|
-
//
|
170
|
+
// Stops a timeout from triggering
|
173
171
|
function clearTimer() {
|
174
|
-
|
172
|
+
// Clear the timeout
|
173
|
+
if (self._timeout) {
|
174
|
+
clearTimeout(self._timeout);
|
175
|
+
self._timeout = null;
|
176
|
+
}
|
177
|
+
|
178
|
+
// Clean up all attached listeners
|
179
|
+
self.removeListener("abort", clearTimer);
|
180
|
+
self.removeListener("error", clearTimer);
|
181
|
+
self.removeListener("response", clearTimer);
|
175
182
|
if (callback) {
|
176
183
|
self.removeListener("timeout", callback);
|
177
184
|
}
|
178
|
-
if (!
|
185
|
+
if (!self.socket) {
|
179
186
|
self._currentRequest.removeListener("socket", startTimer);
|
180
187
|
}
|
181
188
|
}
|
182
189
|
|
183
|
-
//
|
190
|
+
// Attach callback if passed
|
191
|
+
if (callback) {
|
192
|
+
this.on("timeout", callback);
|
193
|
+
}
|
194
|
+
|
195
|
+
// Start the timer if or when the socket is opened
|
184
196
|
if (this.socket) {
|
185
197
|
startTimer(this.socket);
|
186
198
|
}
|
@@ -188,9 +200,11 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
|
|
188
200
|
this._currentRequest.once("socket", startTimer);
|
189
201
|
}
|
190
202
|
|
203
|
+
// Clean up on events
|
191
204
|
this.on("socket", destroyOnTimeout);
|
192
|
-
this.
|
193
|
-
this.
|
205
|
+
this.on("abort", clearTimer);
|
206
|
+
this.on("error", clearTimer);
|
207
|
+
this.on("response", clearTimer);
|
194
208
|
|
195
209
|
return this;
|
196
210
|
};
|
@@ -354,18 +368,32 @@ RedirectableRequest.prototype._processResponse = function (response) {
|
|
354
368
|
}
|
355
369
|
|
356
370
|
// Drop the Host header, as the redirect might lead to a different host
|
357
|
-
var
|
358
|
-
|
371
|
+
var currentHostHeader = removeMatchingHeaders(/^host$/i, this._options.headers);
|
372
|
+
|
373
|
+
// If the redirect is relative, carry over the host of the last request
|
374
|
+
var currentUrlParts = url.parse(this._currentUrl);
|
375
|
+
var currentHost = currentHostHeader || currentUrlParts.host;
|
376
|
+
var currentUrl = /^\w+:/.test(location) ? this._currentUrl :
|
377
|
+
url.format(Object.assign(currentUrlParts, { host: currentHost }));
|
378
|
+
|
379
|
+
// Determine the URL of the redirection
|
380
|
+
var redirectUrl;
|
381
|
+
try {
|
382
|
+
redirectUrl = url.resolve(currentUrl, location);
|
383
|
+
}
|
384
|
+
catch (cause) {
|
385
|
+
this.emit("error", new RedirectionError(cause));
|
386
|
+
return;
|
387
|
+
}
|
359
388
|
|
360
389
|
// Create the redirected request
|
361
|
-
var redirectUrl = url.resolve(this._currentUrl, location);
|
362
390
|
debug("redirecting to", redirectUrl);
|
363
391
|
this._isRedirect = true;
|
364
392
|
var redirectUrlParts = url.parse(redirectUrl);
|
365
393
|
Object.assign(this._options, redirectUrlParts);
|
366
394
|
|
367
|
-
// Drop the Authorization header if redirecting to another
|
368
|
-
if (redirectUrlParts.
|
395
|
+
// Drop the Authorization header if redirecting to another domain
|
396
|
+
if (!(redirectUrlParts.host === currentHost || isSubdomainOf(redirectUrlParts.host, currentHost))) {
|
369
397
|
removeMatchingHeaders(/^authorization$/i, this._options.headers);
|
370
398
|
}
|
371
399
|
|
@@ -387,9 +415,7 @@ RedirectableRequest.prototype._processResponse = function (response) {
|
|
387
415
|
this._performRequest();
|
388
416
|
}
|
389
417
|
catch (cause) {
|
390
|
-
|
391
|
-
error.cause = cause;
|
392
|
-
this.emit("error", error);
|
418
|
+
this.emit("error", new RedirectionError(cause));
|
393
419
|
}
|
394
420
|
}
|
395
421
|
else {
|
@@ -499,7 +525,7 @@ function removeMatchingHeaders(regex, headers) {
|
|
499
525
|
var lastValue;
|
500
526
|
for (var header in headers) {
|
501
527
|
if (regex.test(header)) {
|
502
|
-
lastValue = headers[header];
|
528
|
+
lastValue = headers[header].toString().trim();
|
503
529
|
delete headers[header];
|
504
530
|
}
|
505
531
|
}
|
@@ -507,9 +533,15 @@ function removeMatchingHeaders(regex, headers) {
|
|
507
533
|
}
|
508
534
|
|
509
535
|
function createErrorType(code, defaultMessage) {
|
510
|
-
function CustomError(
|
536
|
+
function CustomError(cause) {
|
511
537
|
Error.captureStackTrace(this, this.constructor);
|
512
|
-
|
538
|
+
if (!cause) {
|
539
|
+
this.message = defaultMessage;
|
540
|
+
}
|
541
|
+
else {
|
542
|
+
this.message = defaultMessage + ": " + cause.message;
|
543
|
+
this.cause = cause;
|
544
|
+
}
|
513
545
|
}
|
514
546
|
CustomError.prototype = new Error();
|
515
547
|
CustomError.prototype.constructor = CustomError;
|
@@ -526,6 +558,11 @@ function abortRequest(request) {
|
|
526
558
|
request.abort();
|
527
559
|
}
|
528
560
|
|
561
|
+
function isSubdomainOf(subdomain, domain) {
|
562
|
+
const dot = subdomain.length - domain.length - 1;
|
563
|
+
return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain);
|
564
|
+
}
|
565
|
+
|
529
566
|
// Exports
|
530
567
|
module.exports = wrap({ http: http, https: https });
|
531
568
|
module.exports.wrap = wrap;
|