follow-redirects
Advanced tools
Comparing version 1.5.10 to 1.6.0
125
index.js
var url = require("url"); | ||
var URL = url.URL; | ||
var http = require("http"); | ||
@@ -26,2 +27,4 @@ var https = require("https"); | ||
this._options = options; | ||
this._ended = false; | ||
this._ending = false; | ||
this._redirectCount = 0; | ||
@@ -73,2 +76,7 @@ this._redirects = []; | ||
RedirectableRequest.prototype.write = function (data, encoding, callback) { | ||
// Writing is not allowed if end has been called | ||
if (this._ending) { | ||
throw new Error("write after end"); | ||
} | ||
// Validate input and shift parameters if necessary | ||
@@ -116,7 +124,16 @@ if (!(typeof data === "string" || typeof data === "object" && ("length" in data))) { | ||
// Write data and end | ||
var currentRequest = this._currentRequest; | ||
this.write(data || "", encoding, function () { | ||
currentRequest.end(null, null, callback); | ||
}); | ||
// Write data if needed and end | ||
if (!data) { | ||
this._ended = this._ending = true; | ||
this._currentRequest.end(null, null, callback); | ||
} | ||
else { | ||
var self = this; | ||
var currentRequest = this._currentRequest; | ||
this.write(data, encoding, function () { | ||
self._ended = true; | ||
currentRequest.end(null, null, callback); | ||
}); | ||
this._ending = true; | ||
} | ||
}; | ||
@@ -189,11 +206,26 @@ | ||
var i = 0; | ||
var self = this; | ||
var buffers = this._requestBodyBuffers; | ||
(function writeNext() { | ||
if (i < buffers.length) { | ||
var buffer = buffers[i++]; | ||
request.write(buffer.data, buffer.encoding, writeNext); | ||
(function writeNext(error) { | ||
// Only write if this request has not been redirected yet | ||
/* istanbul ignore else */ | ||
if (request === self._currentRequest) { | ||
// Report any write errors | ||
/* istanbul ignore if */ | ||
if (error) { | ||
self.emit("error", error); | ||
} | ||
// Write the next buffer if there are still left | ||
else if (i < buffers.length) { | ||
var buffer = buffers[i++]; | ||
/* istanbul ignore else */ | ||
if (!request.finished) { | ||
request.write(buffer.data, buffer.encoding, writeNext); | ||
} | ||
} | ||
// End the request if `end` has been called on us | ||
else if (self._ended) { | ||
request.end(); | ||
} | ||
} | ||
else { | ||
request.end(); | ||
} | ||
}()); | ||
@@ -223,2 +255,7 @@ } | ||
response.statusCode >= 300 && response.statusCode < 400) { | ||
// Abort the current request | ||
this._currentRequest.removeAllListeners(); | ||
this._currentRequest.on("error", noop); | ||
this._currentRequest.abort(); | ||
// RFC7231§6.4: A client SHOULD detect and intervene | ||
@@ -297,15 +334,34 @@ // in cyclical redirections (i.e., "infinite" redirection loops). | ||
// Executes a request, following redirects | ||
wrappedProtocol.request = function (options, callback) { | ||
if (typeof options === "string") { | ||
options = url.parse(options); | ||
options.maxRedirects = exports.maxRedirects; | ||
wrappedProtocol.request = function (input, options, callback) { | ||
// Parse parameters | ||
if (typeof input === "string") { | ||
var urlStr = input; | ||
try { | ||
input = urlToOptions(new URL(urlStr)); | ||
} | ||
catch (err) { | ||
/* istanbul ignore next */ | ||
input = url.parse(urlStr); | ||
} | ||
} | ||
else if (URL && (input instanceof URL)) { | ||
input = urlToOptions(input); | ||
} | ||
else { | ||
options = Object.assign({ | ||
protocol: protocol, | ||
maxRedirects: exports.maxRedirects, | ||
maxBodyLength: exports.maxBodyLength, | ||
}, options); | ||
callback = options; | ||
options = input; | ||
input = { protocol: protocol }; | ||
} | ||
if (typeof options === "function") { | ||
callback = options; | ||
options = null; | ||
} | ||
// Set defaults | ||
options = Object.assign({ | ||
maxRedirects: exports.maxRedirects, | ||
maxBodyLength: exports.maxBodyLength, | ||
}, input, options); | ||
options.nativeProtocols = nativeProtocols; | ||
assert.equal(options.protocol, protocol, "protocol mismatch"); | ||
@@ -317,4 +373,4 @@ debug("options", options); | ||
// Executes a GET request, following redirects | ||
wrappedProtocol.get = function (options, callback) { | ||
var request = wrappedProtocol.request(options, callback); | ||
wrappedProtocol.get = function (input, options, callback) { | ||
var request = wrappedProtocol.request(input, options, callback); | ||
request.end(); | ||
@@ -327,4 +383,27 @@ return request; | ||
/* istanbul ignore next */ | ||
function noop() { /* empty */ } | ||
// from https://github.com/nodejs/node/blob/master/lib/internal/url.js | ||
function urlToOptions(urlObject) { | ||
var options = { | ||
protocol: urlObject.protocol, | ||
hostname: urlObject.hostname.startsWith("[") ? | ||
/* istanbul ignore next */ | ||
urlObject.hostname.slice(1, -1) : | ||
urlObject.hostname, | ||
hash: urlObject.hash, | ||
search: urlObject.search, | ||
pathname: urlObject.pathname, | ||
path: `${urlObject.pathname}${urlObject.search}`, | ||
href: urlObject.href, | ||
}; | ||
if (urlObject.port !== "") { | ||
options.port = Number(urlObject.port); | ||
} | ||
return options; | ||
} | ||
// Exports | ||
module.exports = wrap({ http: http, https: https }); | ||
module.exports.wrap = wrap; |
{ | ||
"name": "follow-redirects", | ||
"version": "1.5.10", | ||
"version": "1.6.0", | ||
"description": "HTTP and HTTPS modules that follow redirects.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -155,2 +155,2 @@ ## Follow Redirects | ||
[https://github.com/follow-redirects/follow-redirects/blob/master/LICENSE](MIT License) | ||
[MIT License](https://github.com/follow-redirects/follow-redirects/blob/master/LICENSE) |
21984
364