follow-redirects
Advanced tools
Comparing version 0.0.5 to 0.0.6
138
index.js
@@ -1,134 +0,4 @@ | ||
var nativeHttps = require('https'), | ||
nativeHttp = require('http'), | ||
url = require('url'), | ||
_ = require('underscore'), | ||
debug = require('debug')('follow-redirects'); | ||
var maxRedirects = module.exports.maxRedirects = 5; | ||
var protocols = { | ||
https: nativeHttps, | ||
http: nativeHttp | ||
}; | ||
// Only use GETs on redirects | ||
for (var protocol in protocols) { | ||
// h is either our cloned http or https object | ||
var h = function() {}; | ||
h.prototype = protocols[protocol]; | ||
h = new h(); | ||
module.exports[protocol] = h; | ||
h.request = function (h) { | ||
return function (options, callback, redirectOptions) { | ||
redirectOptions = redirectOptions || {}; | ||
var max = (typeof options === 'object' && 'maxRedirects' in options) ? options.maxRedirects : exports.maxRedirects; | ||
var redirect = _.extend({ | ||
count: 0, | ||
max: max, | ||
clientRequest: null, | ||
userCallback: callback | ||
}, redirectOptions); | ||
/** | ||
* Emit error if too many redirects | ||
*/ | ||
if (redirect.count > redirect.max) { | ||
var err = new Error('Max redirects exceeded. To allow more redirects, pass options.maxRedirects property.'); | ||
redirect.clientRequest.emit('error', err); | ||
return redirect.clientRequest; | ||
} | ||
redirect.count++; | ||
/** | ||
* Parse URL from options | ||
*/ | ||
var reqUrl, method; | ||
if (typeof options === 'string') { | ||
reqUrl = options; | ||
} | ||
else { | ||
reqUrl = url.format(_.extend({ protocol: protocol }, options)); | ||
} | ||
/* | ||
* Build client request | ||
*/ | ||
debug(options); | ||
var clientRequest = h.__proto__.request(options, redirectCallback(reqUrl, redirect)); | ||
// Save user's clientRequest so we can emit errors later | ||
if (!redirect.clientRequest) redirect.clientRequest = clientRequest; | ||
/** | ||
* ClientRequest callback for redirects | ||
*/ | ||
function redirectCallback (reqUrl, redirect) { | ||
debug('redirectCallback'); | ||
return function (res) { | ||
debug('headers:'); | ||
debug(res.headers); | ||
// status must be 300-399 for redirects | ||
if (res.statusCode < 300 || res.statusCode > 399) { | ||
return redirect.userCallback(res); | ||
} | ||
// no `Location:` header => nowhere to redirect | ||
if (!('location' in res.headers)) { | ||
return redirect.userCallback(res); | ||
} | ||
// we are going to follow the redirect, but in node 0.10 we must first attach a data listener | ||
// to consume the stream and send the 'end' event | ||
res.on('data', function() {}); | ||
// save the original clientRequest to our redirectOptions so we can emit errors later | ||
// need to use url.resolve() in case location is a relative URL | ||
var redirectUrl = url.resolve(reqUrl, res.headers['location']); | ||
debug('redirectUrl', redirectUrl); | ||
// we need to call the right api (http vs https) depending on protocol | ||
var proto = url.parse(redirectUrl).protocol; | ||
proto = proto.substr(0, proto.length - 1); | ||
// Make a new option object for next request from old options object | ||
// Break url in parts | ||
var parsedUrl = url.parse(redirectUrl); | ||
var searchname = parsedUrl.search || ''; | ||
var hostname = parsedUrl.hostname; | ||
var pathname = parsedUrl.pathname; | ||
var redirectOptions = typeof options === 'string' ? {} : options; | ||
redirectOptions.reqUrl = redirectUrl; | ||
redirectOptions.hostname = hostname; | ||
redirectOptions.path = pathname + searchname; | ||
debug('redirectOptions', redirectOptions); | ||
var out = module.exports[proto].get(redirectOptions, redirectCallback(reqUrl, redirect), redirect); | ||
// bubble errors that occur on the redirect back up to the initiating client request | ||
// object, otherwise they wind up killing the process. | ||
out.on("error", function(err) { clientRequest.emit("error", err) }); | ||
return out; | ||
}; | ||
} | ||
return clientRequest; | ||
} | ||
}(h); | ||
// see https://github.com/joyent/node/blob/master/lib/http.js#L1623 | ||
h.get = function (h) { | ||
return function (options, cb, redirectOptions) { | ||
var req = h.request(options, cb, redirectOptions); | ||
req.end(); | ||
return req; | ||
}; | ||
}(h); | ||
} | ||
module.exports = require('./create')({ | ||
'http': require('http'), | ||
'https': require('https') | ||
}); |
{ | ||
"name": "follow-redirects", | ||
"version": "0.0.5", | ||
"version": "0.0.6", | ||
"description": "HTTP and HTTPS modules that follow redirects.", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
"test": "npm run cover && npm run lint && npm run style", | ||
"lint": "jshint *.js test/*.js test/**/*.js", | ||
"style": "jscs *.js && jscs test/*.js test/**/*.js --config=test/.jscsrc", | ||
"cover": "BLUEBIRD_DEBUG=1 istanbul cover ./node_modules/.bin/_mocha", | ||
"debug": "BLUEBIRD_DEBUG=1 mocha" | ||
}, | ||
@@ -13,3 +17,6 @@ "repository": { | ||
}, | ||
"homepage": "", | ||
"homepage": "https://github.com/olalonde/follow-redirects", | ||
"bugs": { | ||
"url": "https://github.com/olalonde/follow-redirects/issues" | ||
}, | ||
"keywords": [ | ||
@@ -29,10 +36,26 @@ "http", | ||
}, | ||
"contributors": [ | ||
"James Talmage <james@talmage.io>" | ||
], | ||
"files": [ | ||
"index.js", | ||
"create.js", | ||
"http.js", | ||
"https.js" | ||
], | ||
"dependencies": { | ||
"debug": "^2.2.0", | ||
"underscore": "" | ||
"debug": "^2.2.0" | ||
}, | ||
"devDependencies": { | ||
"colors": "" | ||
"bluebird": "^2.9.30", | ||
"concat-stream": "^1.5.0", | ||
"coveralls": "^2.11.2", | ||
"express": "^4.13.0", | ||
"istanbul": "^0.3.17", | ||
"jscs": "^1.13.1", | ||
"jshint": "^2.8.0", | ||
"mocha": "^2.2.5", | ||
"semver": "~4.3.6" | ||
}, | ||
"license": "MIT" | ||
} |
115
README.md
@@ -1,33 +0,21 @@ | ||
`follow-redirects` extends http and https with the ability to follow | ||
HTTP redirects painlessly. It does not modify the native modules but | ||
instead offers its own http/https modules which inherit from the native | ||
modules. If you want to automatically follow redirects, all you need to | ||
do is replace: | ||
## Follow Redirects | ||
```javascript | ||
var http = require('http'); | ||
``` | ||
Drop in replacement for Nodes `http` and `https` that automatically follows redirects. | ||
by | ||
[![Build Status](https://travis-ci.org/olalonde/follow-redirects.svg?branch=master)](https://travis-ci.org/olalonde/follow-redirects) | ||
[![Coverage Status](https://coveralls.io/repos/olalonde/follow-redirects/badge.svg?branch=master)](https://coveralls.io/r/olalonde/follow-redirects?branch=master) | ||
[![Code Climate](https://codeclimate.com/github/olalonde/follow-redirects/badges/gpa.svg)](https://codeclimate.com/github/olalonde/follow-redirects) | ||
[![Dependency Status](https://david-dm.org/olalonde/follow-redirects.svg)](https://david-dm.org/olalonde/follow-redirects) | ||
[![devDependency Status](https://david-dm.org/olalonde/follow-redirects/dev-status.svg)](https://david-dm.org/olalonde/follow-redirects#info=devDependencies) | ||
```javascript | ||
var http = require('follow-redirects').http; | ||
``` | ||
[![NPM](https://nodei.co/npm/follow-redirects.png?downloads=true)](https://nodei.co/npm/follow-redirects/) | ||
# Install | ||
`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) | ||
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) | ||
modules, with the exception that they will seamlessly follow redirects. | ||
npm install follow-redirects | ||
# Usage | ||
```javascript | ||
var http = require('follow-redirects').http; | ||
var https = require('follow-redirects').https; | ||
/* | ||
* http and https are just like Node.js' http and https modules except | ||
* that they follow redirects seamlessly. | ||
*/ | ||
http.get('http://bit.ly/900913', function (res) { | ||
@@ -40,23 +28,86 @@ res.on('data', function (chunk) { | ||
}); | ||
``` | ||
/* | ||
* You can optionnally pass the maxRedirect option which defaults to 5 | ||
*/ | ||
By default the number of redirects is limited to 5, but you can modify that globally or per request. | ||
```javascript | ||
require('follow-redirects').maxRedirects = 10; // Has global affect (be careful!) | ||
https.request({ | ||
host: 'bitly.com', | ||
path: '/UHfDGO', | ||
maxRedirects: 3 | ||
maxRedirects: 3 // per request setting | ||
}, function (res) {/* ... */}); | ||
``` | ||
You can inspect the redirection chain from the `fetchedUrls` array on the `response`. | ||
The array is populated in reverse order, so the original url you requested will be the | ||
last element, while the final redirection point will be at index 0. | ||
```javascript | ||
https.request({ | ||
host: 'bitly.com', | ||
path: '/UHfDGO', | ||
}, function (res) { | ||
res.on('data', function (chunk) { | ||
console.log(chunk); | ||
}); | ||
}).on('error', function (err) { | ||
console.error(err); | ||
console.log(res.fetchedUrls); | ||
// [ 'http://duckduckgo.com/robots.txt', 'http://bitly.com/UHfDGO' ] | ||
}); | ||
``` | ||
## Browserify Usage | ||
Due to the way `XMLHttpRequest` works, the `browserify` versions of `http` and `https` already follow redirects. | ||
If you are *only* targetting the browser, then this library has little value for you. If you want to write cross | ||
platform code for node and the browser, `follow-redirects` provides a great solution for making the native node | ||
modules behave the same as they do in browserified builds in the browser. To avoid bundling unnecessary code | ||
you should tell browserify to swap out `follow-redirects` with the standard modules when bundling. | ||
To make this easier, you need to change how you require the modules: | ||
```javascript | ||
var http = require('follow-redirects/http'); | ||
var https = require('follow-redirects/https'); | ||
``` | ||
You can then replace `follow-redirects` in your browserify configuration like so: | ||
```javascript | ||
"browser": { | ||
"follow-redirects/http" : "http", | ||
"follow-redirects/https" : "https" | ||
} | ||
``` | ||
The `browserify-http` module has not kept pace with node development, and no long behaves identically to the native | ||
module when running in the browser. If you are experiencing problems, you may want to check out | ||
[browserify-http-2](https://www.npmjs.com/package/http-browserify-2). It is more actively maintained and | ||
attempts to address a few of the shortcomings of `browserify-http`. In that case, your browserify config should | ||
look something like this: | ||
```javascript | ||
"browser": { | ||
"follow-redirects/http" : "browserify-http-2/http", | ||
"follow-redirects/https" : "browserify-http-2/https" | ||
} | ||
``` | ||
## Contributing | ||
Pull Requests are always welcome. Please [file an issue](https://github.com/olalonde/follow-redirects/issues) | ||
detailing your proposal before you invest your valuable time. Additional features and bug fixes should be accompanied | ||
by tests. You can run the test suite locally with a simple `npm test` command. | ||
## Debug Logging | ||
`follow-redirects` uses the excellent [debug](https://www.npmjs.com/package/debug) for logging. To turn on logging | ||
set the environment variable `DEBUG=follow-redirects` for debug output from just this module. When running the test | ||
suite it is sometimes advantageous to set `DEBUG=*` to see output from the express server as well. | ||
## Authors | ||
Olivier Lalonde (olalonde@gmail.com) | ||
James Talmage (james@talmage.io) | ||
## License | ||
MIT: [http://olalonde.mit-license.org](http://olalonde.mit-license.org) |
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
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
Wildcard dependency
QualityPackage has a dependency with a floating version range. This can cause issues if the dependency publishes a new major version.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
11297
1
0
1
0
113
3
9
139
- Removedunderscore@
- Removedunderscore@1.13.7(transitive)