follow-redirects
Advanced tools
Comparing version 0.2.0 to 0.3.0
171
index.js
@@ -1,4 +0,169 @@ | ||
module.exports = require('./create')({ | ||
http: require('http'), | ||
https: require('https') | ||
'use strict'; | ||
var url = require('url'); | ||
var assert = require('assert'); | ||
var http = require('http'); | ||
var https = require('https'); | ||
var Writable = require('stream').Writable; | ||
var debug = require('debug')('follow-redirects'); | ||
var nativeProtocols = {'http:': http, 'https:': https}; | ||
var publicApi = module.exports = { | ||
maxRedirects: 21 | ||
}; | ||
// Wrapper around the native request | ||
function RequestProxy() { | ||
Writable.call(this); | ||
} | ||
RequestProxy.prototype = Object.create(Writable.prototype); | ||
RequestProxy.prototype.abort = function () { | ||
this._request.abort(); | ||
}; | ||
RequestProxy.prototype.end = function (data, encoding, callback) { | ||
this._request.end(data, encoding, callback); | ||
}; | ||
RequestProxy.prototype.flushHeaders = function () { | ||
this._request.flushHeaders(); | ||
}; | ||
RequestProxy.prototype.setNoDelay = function (noDelay) { | ||
this._request.setNoDelay(noDelay); | ||
}; | ||
RequestProxy.prototype.setSocketKeepAlive = function (enable, initialDelay) { | ||
this._request.setSocketKeepAlive(enable, initialDelay); | ||
}; | ||
RequestProxy.prototype.setTimeout = function (timeout, callback) { | ||
this._request.setSocketKeepAlive(timeout, callback); | ||
}; | ||
RequestProxy.prototype._write = function (chunk, encoding, callback) { | ||
this._request.write(chunk, encoding, callback); | ||
}; | ||
function execute(options, callback) { | ||
var fetchedUrls = []; | ||
var requestProxy = new RequestProxy(); | ||
if (callback) { | ||
requestProxy.on('response', callback); | ||
} | ||
cb(); | ||
return requestProxy; | ||
function cb(res) { | ||
// skip the redirection logic on the first call. | ||
if (res) { | ||
var fetchedUrl = url.format(options); | ||
fetchedUrls.unshift(fetchedUrl); | ||
if (!isRedirect(res)) { | ||
res.fetchedUrls = fetchedUrls; | ||
requestProxy.emit('response', res); | ||
return; | ||
} | ||
// need to use url.resolve() in case location is a relative URL | ||
var redirectUrl = url.resolve(fetchedUrl, res.headers.location); | ||
debug('redirecting to', redirectUrl); | ||
extend(options, url.parse(redirectUrl)); | ||
} | ||
if (fetchedUrls.length > options.maxRedirects) { | ||
var err = new Error('Max redirects exceeded.'); | ||
requestProxy.emit('error', err); | ||
return; | ||
} | ||
options.nativeProtocol = nativeProtocols[options.protocol]; | ||
options.defaultRequest = defaultMakeRequest; | ||
var req = (options.makeRequest || defaultMakeRequest)(options, cb, res); | ||
requestProxy._request = req; | ||
mirrorEvent(req, 'abort'); | ||
mirrorEvent(req, 'aborted'); | ||
mirrorEvent(req, 'error'); | ||
return req; | ||
} | ||
function defaultMakeRequest(options, cb, res) { | ||
if (res && res.statusCode !== 307) { | ||
// This is a redirect, so use only GET methods, except for status 307, | ||
// which must honor the previous request method. | ||
options.method = 'GET'; | ||
} | ||
var req = options.nativeProtocol.request(options, cb); | ||
if (res) { | ||
// We leave the user to call `end` on the first request | ||
req.end(); | ||
} | ||
return req; | ||
} | ||
// send events through the proxy | ||
function mirrorEvent(req, event) { | ||
req.on(event, function (arg) { | ||
requestProxy.emit(event, arg); | ||
}); | ||
} | ||
} | ||
// returns a safe copy of options (or a parsed url object if options was a string). | ||
// validates that the supplied callback is a function | ||
function parseOptions(options, wrappedProtocol) { | ||
if (typeof options === 'string') { | ||
options = url.parse(options); | ||
options.maxRedirects = publicApi.maxRedirects; | ||
} else { | ||
options = extend({ | ||
maxRedirects: publicApi.maxRedirects, | ||
protocol: wrappedProtocol | ||
}, options); | ||
} | ||
assert.equal(options.protocol, wrappedProtocol, 'protocol mismatch'); | ||
debug('options', options); | ||
return options; | ||
} | ||
// copies source's own properties onto destination and returns destination | ||
function extend(destination, source) { | ||
var keys = Object.keys(source); | ||
for (var i = 0; i < keys.length; i++) { | ||
var key = keys[i]; | ||
destination[key] = source[key]; | ||
} | ||
return destination; | ||
} | ||
// to redirect the result must have | ||
// a statusCode between 300-399 | ||
// and a `Location` header | ||
function isRedirect(res) { | ||
return (res.statusCode >= 300 && res.statusCode <= 399 && | ||
'location' in res.headers); | ||
} | ||
Object.keys(nativeProtocols).forEach(function (wrappedProtocol) { | ||
var scheme = wrappedProtocol.substr(0, wrappedProtocol.length - 1); | ||
var nativeProtocol = nativeProtocols[wrappedProtocol]; | ||
var protocol = publicApi[scheme] = Object.create(nativeProtocol); | ||
protocol.request = function (options, callback) { | ||
return execute(parseOptions(options, wrappedProtocol), callback); | ||
}; | ||
// see https://github.com/joyent/node/blob/master/lib/http.js#L1623 | ||
protocol.get = function (options, callback) { | ||
var req = execute(parseOptions(options, wrappedProtocol), callback); | ||
req.end(); | ||
return req; | ||
}; | ||
}); |
{ | ||
"name": "follow-redirects", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"description": "HTTP and HTTPS modules that follow redirects.", | ||
@@ -41,4 +41,3 @@ "main": "index.js", | ||
"dependencies": { | ||
"debug": "^2.2.0", | ||
"stream-consume": "^0.1.0" | ||
"debug": "^2.2.0" | ||
}, | ||
@@ -50,6 +49,6 @@ "devDependencies": { | ||
"express": "^4.13.0", | ||
"mocha": "^2.2.5", | ||
"nyc": "^6.4.4", | ||
"semver": "~5.1.0", | ||
"xo": "^0.15.1" | ||
"mocha": "^3.1.2", | ||
"nyc": "^8.3.1", | ||
"semver": "^5.3.0", | ||
"xo": "^0.17.0" | ||
}, | ||
@@ -56,0 +55,0 @@ "license": "MIT", |
@@ -5,2 +5,3 @@ ## Follow Redirects | ||
[![npm version](https://badge.fury.io/js/follow-redirects.svg)](https://www.npmjs.com/package/follow-redirects) | ||
[![Build Status](https://travis-ci.org/olalonde/follow-redirects.svg?branch=master)](https://travis-ci.org/olalonde/follow-redirects) | ||
@@ -7,0 +8,0 @@ [![Coverage Status](https://coveralls.io/repos/olalonde/follow-redirects/badge.svg?branch=master)](https://coveralls.io/r/olalonde/follow-redirects?branch=master) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1
114
10937
5
142
4
- Removedstream-consume@^0.1.0
- Removedstream-consume@0.1.1(transitive)