Permalink
Browse files

Merge pull request #90 from jroes/follow-post-put-redirects

add option followAllRedirects to follow post/put redirects
  • Loading branch information...
2 parents 70c5b63 + d2d9b54 commit 00105c2874c18b1a2b5c0dcd1b2a13566a5a1c63 @mikeal mikeal committed Feb 4, 2012
Showing with 49 additions and 7 deletions.
  1. +1 โˆ’0 README.md
  2. +6 โˆ’6 main.js
  3. +42 โˆ’1 tests/test-redirect.js
View
@@ -153,6 +153,7 @@ The first argument can be either a url or an options object. The only required o
* `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header.
* `multipart` - (experimental) array of objects which contains their own headers and `body` attribute. Sends `multipart/related` request. See example below.
* `followRedirect` - follow HTTP 3xx responses as redirects. defaults to true.
+* `followAllRedirects` - follow non-GET HTTP 3xx responses as redirects. defaults to false.
* `maxRedirects` - the maximum number of redirects to follow, defaults to 10.
* `onResponse` - If true the callback will be fired on the "response" event instead of "end". If a function it will be called on "response" and not effect the regular semantics of the main callback on "end".
* `encoding` - Encoding to be used on `setEncoding` of response data. If set to `null`, the body is returned as a Buffer.
View
12 main.js
@@ -129,7 +129,8 @@ Request.prototype.request = function () {
self._redirectsFollowed = self._redirectsFollowed || 0
self.maxRedirects = (self.maxRedirects !== undefined) ? self.maxRedirects : 10
self.followRedirect = (self.followRedirect !== undefined) ? self.followRedirect : true
- if (self.followRedirect)
+ self.followAllRedirects = (self.followAllRedirects !== undefined) ? self.followAllRedirects : false;
+ if (self.followRedirect || self.followAllRedirects)
self.redirects = self.redirects || []
self.headers = self.headers ? copy(self.headers) : {}
@@ -367,11 +368,9 @@ Request.prototype.request = function () {
})
}
- if (response.statusCode >= 300 &&
- response.statusCode < 400 &&
- self.followRedirect &&
- self.method !== 'PUT' &&
- self.method !== 'POST' &&
+ if (response.statusCode >= 300 && response.statusCode < 400 &&
+ (self.followAllRedirects ||
+ (self.followRedirect && (self.method !== 'PUT' && self.method !== 'POST'))) &&
response.headers.location) {
if (self._redirectsFollowed >= self.maxRedirects) {
self.emit('error', new Error("Exceeded maxRedirects. Probably stuck in a redirect loop."))
@@ -388,6 +387,7 @@ Request.prototype.request = function () {
, redirectUri: response.headers.location
}
)
+ self.method = 'GET'; // Force all redirects to use GET
delete self.req
delete self.agent
delete self._started
View
@@ -23,6 +23,12 @@ s.listen(s.port, function () {
})
s.on('/'+landing, function (req, res) {
+ if (req.method !== 'GET') { // We should only accept GET redirects
+ console.error("Got a non-GET request to the redirect destination URL");
+ resp.writeHead(400);
+ resp.end();
+ return;
+ }
hits[landing] = true;
res.writeHead(200)
res.end(landing)
@@ -65,10 +71,45 @@ s.listen(s.port, function () {
}
})
+ // Should not follow post redirects by default
+ request.post({uri:server+'/temp'}, function (er, res, body) {
+ try {
+ assert.ok(hits.temp, 'Original request is to /temp')
+ assert.ok(!hits.temp_landing, 'No chasing the redirect when post')
+ assert.equal(res.statusCode, 301, 'Response is the bounce itself')
+ passed += 1
+ } finally {
+ done()
+ }
+ })
+
+ // Should follow post redirects when followAllRedirects true
+ request.post({uri:server+'/temp', followAllRedirects:true}, function (er, res, body) {
+ try {
+ assert.ok(hits.temp, 'Original request is to /temp')
+ assert.ok(hits.temp_landing, 'Forward to temporary landing URL')
+ assert.equal(body, 'temp_landing', 'Got temporary landing content')
+ passed += 1
+ } finally {
+ done()
+ }
+ })
+
+ request.post({uri:server+'/temp', followAllRedirects:false}, function (er, res, body) {
+ try {
+ assert.ok(hits.temp, 'Original request is to /temp')
+ assert.ok(!hits.temp_landing, 'No chasing the redirect')
+ assert.equal(res.statusCode, 301, 'Response is the bounce itself')
+ passed += 1
+ } finally {
+ done()
+ }
+ })
+
var reqs_done = 0;
function done() {
reqs_done += 1;
- if(reqs_done == 3) {
+ if(reqs_done == 6) {
console.log(passed + ' tests passed.')
s.close()
}

0 comments on commit 00105c2

Please sign in to comment.