| 'use strict' | 
|   | 
| var url = require('url') | 
| var isUrl = /^https?:/ | 
|   | 
| function Redirect (request) { | 
|   this.request = request | 
|   this.followRedirect = true | 
|   this.followRedirects = true | 
|   this.followAllRedirects = false | 
|   this.followOriginalHttpMethod = false | 
|   this.allowRedirect = function () { return true } | 
|   this.maxRedirects = 10 | 
|   this.redirects = [] | 
|   this.redirectsFollowed = 0 | 
|   this.removeRefererHeader = false | 
| } | 
|   | 
| Redirect.prototype.onRequest = function (options) { | 
|   var self = this | 
|   | 
|   if (options.maxRedirects !== undefined) { | 
|     self.maxRedirects = options.maxRedirects | 
|   } | 
|   if (typeof options.followRedirect === 'function') { | 
|     self.allowRedirect = options.followRedirect | 
|   } | 
|   if (options.followRedirect !== undefined) { | 
|     self.followRedirects = !!options.followRedirect | 
|   } | 
|   if (options.followAllRedirects !== undefined) { | 
|     self.followAllRedirects = options.followAllRedirects | 
|   } | 
|   if (self.followRedirects || self.followAllRedirects) { | 
|     self.redirects = self.redirects || [] | 
|   } | 
|   if (options.removeRefererHeader !== undefined) { | 
|     self.removeRefererHeader = options.removeRefererHeader | 
|   } | 
|   if (options.followOriginalHttpMethod !== undefined) { | 
|     self.followOriginalHttpMethod = options.followOriginalHttpMethod | 
|   } | 
| } | 
|   | 
| Redirect.prototype.redirectTo = function (response) { | 
|   var self = this | 
|   var request = self.request | 
|   | 
|   var redirectTo = null | 
|   if (response.statusCode >= 300 && response.statusCode < 400 && response.caseless.has('location')) { | 
|     var location = response.caseless.get('location') | 
|     request.debug('redirect', location) | 
|   | 
|     if (self.followAllRedirects) { | 
|       redirectTo = location | 
|     } else if (self.followRedirects) { | 
|       switch (request.method) { | 
|         case 'PATCH': | 
|         case 'PUT': | 
|         case 'POST': | 
|         case 'DELETE': | 
|           // Do not follow redirects | 
|           break | 
|         default: | 
|           redirectTo = location | 
|           break | 
|       } | 
|     } | 
|   } else if (response.statusCode === 401) { | 
|     var authHeader = request._auth.onResponse(response) | 
|     if (authHeader) { | 
|       request.setHeader('authorization', authHeader) | 
|       redirectTo = request.uri | 
|     } | 
|   } | 
|   return redirectTo | 
| } | 
|   | 
| Redirect.prototype.onResponse = function (response) { | 
|   var self = this | 
|   var request = self.request | 
|   | 
|   var redirectTo = self.redirectTo(response) | 
|   if (!redirectTo || !self.allowRedirect.call(request, response)) { | 
|     return false | 
|   } | 
|   | 
|   request.debug('redirect to', redirectTo) | 
|   | 
|   // ignore any potential response body.  it cannot possibly be useful | 
|   // to us at this point. | 
|   // response.resume should be defined, but check anyway before calling. Workaround for browserify. | 
|   if (response.resume) { | 
|     response.resume() | 
|   } | 
|   | 
|   if (self.redirectsFollowed >= self.maxRedirects) { | 
|     request.emit('error', new Error('Exceeded maxRedirects. Probably stuck in a redirect loop ' + request.uri.href)) | 
|     return false | 
|   } | 
|   self.redirectsFollowed += 1 | 
|   | 
|   if (!isUrl.test(redirectTo)) { | 
|     redirectTo = url.resolve(request.uri.href, redirectTo) | 
|   } | 
|   | 
|   var uriPrev = request.uri | 
|   request.uri = url.parse(redirectTo) | 
|   | 
|   // handle the case where we change protocol from https to http or vice versa | 
|   if (request.uri.protocol !== uriPrev.protocol) { | 
|     delete request.agent | 
|   } | 
|   | 
|   self.redirects.push({ statusCode: response.statusCode, redirectUri: redirectTo }) | 
|   | 
|   if (self.followAllRedirects && request.method !== 'HEAD' && | 
|     response.statusCode !== 401 && response.statusCode !== 307) { | 
|     request.method = self.followOriginalHttpMethod ? request.method : 'GET' | 
|   } | 
|   // request.method = 'GET' // Force all redirects to use GET || commented out fixes #215 | 
|   delete request.src | 
|   delete request.req | 
|   delete request._started | 
|   if (response.statusCode !== 401 && response.statusCode !== 307) { | 
|     // Remove parameters from the previous response, unless this is the second request | 
|     // for a server that requires digest authentication. | 
|     delete request.body | 
|     delete request._form | 
|     if (request.headers) { | 
|       request.removeHeader('host') | 
|       request.removeHeader('content-type') | 
|       request.removeHeader('content-length') | 
|       if (request.uri.hostname !== request.originalHost.split(':')[0]) { | 
|         // Remove authorization if changing hostnames (but not if just | 
|         // changing ports or protocols).  This matches the behavior of curl: | 
|         // https://github.com/bagder/curl/blob/6beb0eee/lib/http.c#L710 | 
|         request.removeHeader('authorization') | 
|       } | 
|     } | 
|   } | 
|   | 
|   if (!self.removeRefererHeader) { | 
|     request.setHeader('referer', uriPrev.href) | 
|   } | 
|   | 
|   request.emit('redirect') | 
|   | 
|   request.init() | 
|   | 
|   return true | 
| } | 
|   | 
| exports.Redirect = Redirect |