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 CHANGED
@@ -6,6 +6,7 @@ Drop-in replacement for Node's `http` and `https` modules that automatically fol
6
6
  [![Build Status](https://travis-ci.org/follow-redirects/follow-redirects.svg?branch=master)](https://travis-ci.org/follow-redirects/follow-redirects)
7
7
  [![Coverage Status](https://coveralls.io/repos/follow-redirects/follow-redirects/badge.svg?branch=master)](https://coveralls.io/r/follow-redirects/follow-redirects?branch=master)
8
8
  [![npm downloads](https://img.shields.io/npm/dm/follow-redirects.svg)](https://www.npmjs.com/package/follow-redirects)
9
+ [![Sponsor on GitHub](https://img.shields.io/static/v1?label=Sponsor&message=%F0%9F%92%96&logo=GitHub)](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
@@ -0,0 +1,9 @@
1
+ var debug;
2
+ try {
3
+ /* eslint global-require: off */
4
+ debug = require("debug")("follow-redirects");
5
+ }
6
+ catch (error) {
7
+ debug = function () { /* */ };
8
+ }
9
+ module.exports = debug;
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 debug = require("debug")("follow-redirects");
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 Error("write after end");
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 Error("data should be a string, Buffer or Uint8Array");
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 Error("Request body larger than maxBodyLength limit"));
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 Error("Unsupported protocol " + protocol));
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 Error("Max redirects exceeded."));
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
- if (!this._isRedirect) {
321
- removeMatchingHeaders(/^host$/i, this._options.headers);
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
- Object.assign(this._options, url.parse(redirectUrl));
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 Error("Cannot redirect: " + cause.message);
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.9.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
- "dependencies": {
41
- "debug": "^3.0.0"
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",