follow-redirects 1.9.1 → 1.12.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.
Potentially problematic release.
This version of follow-redirects might be problematic. Click here for more details.
- package/README.md +1 -0
- package/debug.js +9 -0
- package/index.js +50 -12
- package/package.json +7 -4
package/README.md
CHANGED
@@ -6,6 +6,7 @@ Drop-in replacement for Node's `http` and `https` modules that automatically fol
|
|
6
6
|
[](https://travis-ci.org/follow-redirects/follow-redirects)
|
7
7
|
[](https://coveralls.io/r/follow-redirects/follow-redirects?branch=master)
|
8
8
|
[](https://www.npmjs.com/package/follow-redirects)
|
9
|
+
[](https://github.com/sponsors/RubenVerborgh)
|
9
10
|
|
10
11
|
`follow-redirects` provides [request](https://nodejs.org/api/http.html#http_http_request_options_callback) and [get](https://nodejs.org/api/http.html#http_http_get_options_callback)
|
11
12
|
methods that behave identically to those found on the native [http](https://nodejs.org/api/http.html#http_http_request_options_callback) and [https](https://nodejs.org/api/https.html#https_https_request_options_callback)
|
package/debug.js
ADDED
package/index.js
CHANGED
@@ -2,9 +2,9 @@ var url = require("url");
|
|
2
2
|
var URL = url.URL;
|
3
3
|
var http = require("http");
|
4
4
|
var https = require("https");
|
5
|
-
var assert = require("assert");
|
6
5
|
var Writable = require("stream").Writable;
|
7
|
-
var
|
6
|
+
var assert = require("assert");
|
7
|
+
var debug = require("./debug");
|
8
8
|
|
9
9
|
// Create handlers that pass events from native requests
|
10
10
|
var eventHandlers = Object.create(null);
|
@@ -14,6 +14,24 @@ var eventHandlers = Object.create(null);
|
|
14
14
|
};
|
15
15
|
});
|
16
16
|
|
17
|
+
// Error types with codes
|
18
|
+
var RedirectionError = createErrorType(
|
19
|
+
"ERR_FR_REDIRECTION_FAILURE",
|
20
|
+
""
|
21
|
+
);
|
22
|
+
var TooManyRedirectsError = createErrorType(
|
23
|
+
"ERR_FR_TOO_MANY_REDIRECTS",
|
24
|
+
"Maximum number of redirects exceeded"
|
25
|
+
);
|
26
|
+
var MaxBodyLengthExceededError = createErrorType(
|
27
|
+
"ERR_FR_MAX_BODY_LENGTH_EXCEEDED",
|
28
|
+
"Request body larger than maxBodyLength limit"
|
29
|
+
);
|
30
|
+
var WriteAfterEndError = createErrorType(
|
31
|
+
"ERR_STREAM_WRITE_AFTER_END",
|
32
|
+
"write after end"
|
33
|
+
);
|
34
|
+
|
17
35
|
// An HTTP(S) request that can be redirected
|
18
36
|
function RedirectableRequest(options, responseCallback) {
|
19
37
|
// Initialize the request
|
@@ -47,12 +65,12 @@ RedirectableRequest.prototype = Object.create(Writable.prototype);
|
|
47
65
|
RedirectableRequest.prototype.write = function (data, encoding, callback) {
|
48
66
|
// Writing is not allowed if end has been called
|
49
67
|
if (this._ending) {
|
50
|
-
throw new
|
68
|
+
throw new WriteAfterEndError();
|
51
69
|
}
|
52
70
|
|
53
71
|
// Validate input and shift parameters if necessary
|
54
72
|
if (!(typeof data === "string" || typeof data === "object" && ("length" in data))) {
|
55
|
-
throw new
|
73
|
+
throw new TypeError("data should be a string, Buffer or Uint8Array");
|
56
74
|
}
|
57
75
|
if (typeof encoding === "function") {
|
58
76
|
callback = encoding;
|
@@ -75,7 +93,7 @@ RedirectableRequest.prototype.write = function (data, encoding, callback) {
|
|
75
93
|
}
|
76
94
|
// Error when we exceed the maximum body length
|
77
95
|
else {
|
78
|
-
this.emit("error", new
|
96
|
+
this.emit("error", new MaxBodyLengthExceededError());
|
79
97
|
this.abort();
|
80
98
|
}
|
81
99
|
};
|
@@ -207,7 +225,7 @@ RedirectableRequest.prototype._performRequest = function () {
|
|
207
225
|
var protocol = this._options.protocol;
|
208
226
|
var nativeProtocol = this._options.nativeProtocols[protocol];
|
209
227
|
if (!nativeProtocol) {
|
210
|
-
this.emit("error", new
|
228
|
+
this.emit("error", new TypeError("Unsupported protocol " + protocol));
|
211
229
|
return;
|
212
230
|
}
|
213
231
|
|
@@ -296,7 +314,7 @@ RedirectableRequest.prototype._processResponse = function (response) {
|
|
296
314
|
// RFC7231§6.4: A client SHOULD detect and intervene
|
297
315
|
// in cyclical redirections (i.e., "infinite" redirection loops).
|
298
316
|
if (++this._redirectCount > this._options.maxRedirects) {
|
299
|
-
this.emit("error", new
|
317
|
+
this.emit("error", new TooManyRedirectsError());
|
300
318
|
return;
|
301
319
|
}
|
302
320
|
|
@@ -317,15 +335,20 @@ RedirectableRequest.prototype._processResponse = function (response) {
|
|
317
335
|
}
|
318
336
|
|
319
337
|
// Drop the Host header, as the redirect might lead to a different host
|
320
|
-
|
321
|
-
|
322
|
-
}
|
338
|
+
var previousHostName = removeMatchingHeaders(/^host$/i, this._options.headers) ||
|
339
|
+
url.parse(this._currentUrl).hostname;
|
323
340
|
|
324
341
|
// Create the redirected request
|
325
342
|
var redirectUrl = url.resolve(this._currentUrl, location);
|
326
343
|
debug("redirecting to", redirectUrl);
|
327
344
|
this._isRedirect = true;
|
328
|
-
|
345
|
+
var redirectUrlParts = url.parse(redirectUrl);
|
346
|
+
Object.assign(this._options, redirectUrlParts);
|
347
|
+
|
348
|
+
// Drop the Authorization header if redirecting to another host
|
349
|
+
if (redirectUrlParts.hostname !== previousHostName) {
|
350
|
+
removeMatchingHeaders(/^authorization$/i, this._options.headers);
|
351
|
+
}
|
329
352
|
|
330
353
|
// Evaluate the beforeRedirect callback
|
331
354
|
if (typeof this._options.beforeRedirect === "function") {
|
@@ -344,7 +367,7 @@ RedirectableRequest.prototype._processResponse = function (response) {
|
|
344
367
|
this._performRequest();
|
345
368
|
}
|
346
369
|
catch (cause) {
|
347
|
-
var error = new
|
370
|
+
var error = new RedirectionError("Redirected request failed: " + cause.message);
|
348
371
|
error.cause = cause;
|
349
372
|
this.emit("error", error);
|
350
373
|
}
|
@@ -447,11 +470,26 @@ function urlToOptions(urlObject) {
|
|
447
470
|
}
|
448
471
|
|
449
472
|
function removeMatchingHeaders(regex, headers) {
|
473
|
+
var lastValue;
|
450
474
|
for (var header in headers) {
|
451
475
|
if (regex.test(header)) {
|
476
|
+
lastValue = headers[header];
|
452
477
|
delete headers[header];
|
453
478
|
}
|
454
479
|
}
|
480
|
+
return lastValue;
|
481
|
+
}
|
482
|
+
|
483
|
+
function createErrorType(code, defaultMessage) {
|
484
|
+
function CustomError(message) {
|
485
|
+
Error.captureStackTrace(this, this.constructor);
|
486
|
+
this.message = message || defaultMessage;
|
487
|
+
}
|
488
|
+
CustomError.prototype = new Error();
|
489
|
+
CustomError.prototype.constructor = CustomError;
|
490
|
+
CustomError.prototype.name = "Error [" + code + "]";
|
491
|
+
CustomError.prototype.code = code;
|
492
|
+
return CustomError;
|
455
493
|
}
|
456
494
|
|
457
495
|
// Exports
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "follow-redirects",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.12.1",
|
4
4
|
"description": "HTTP and HTTPS modules that follow redirects.",
|
5
5
|
"license": "MIT",
|
6
6
|
"main": "index.js",
|
@@ -37,9 +37,12 @@
|
|
37
37
|
"Olivier Lalonde <olalonde@gmail.com> (http://www.syskall.com)",
|
38
38
|
"James Talmage <james@talmage.io>"
|
39
39
|
],
|
40
|
-
"
|
41
|
-
|
42
|
-
|
40
|
+
"funding": [
|
41
|
+
{
|
42
|
+
"type": "individual",
|
43
|
+
"url": "https://github.com/sponsors/RubenVerborgh"
|
44
|
+
}
|
45
|
+
],
|
43
46
|
"devDependencies": {
|
44
47
|
"concat-stream": "^2.0.0",
|
45
48
|
"eslint": "^5.16.0",
|