From 96d237e7b3705d05dbcad1914de9990d8740e4f3 Mon Sep 17 00:00:00 2001 From: Rob Wu Date: Wed, 28 Aug 2013 18:49:51 +0200 Subject: [PATCH] [WIP] Support internal redirects TODO: - Move proxyRequest elsewhere, and attach the request state to req - Investigate the implications of calling req.emit('end'); (It's called in order to trigger reverseProxy.end(), needed to start the redirect) --- lib/cors-anywhere.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/cors-anywhere.js b/lib/cors-anywhere.js index cf5ba6a..ebd12b6 100644 --- a/lib/cors-anywhere.js +++ b/lib/cors-anywhere.js @@ -86,6 +86,8 @@ function isForbidden(host) { * @param proxy {HttpProxy} * @param location {object} See parseURL * @param requestState.proxyBaseUrl {string} Base URL of the CORS API endpoint. + * @param requestState.maxRedirects {number} Maximum number of redirects + * @param requestState.redirectCount_ {number} Internally used to count redirects */ function proxyRequest(req, res, proxy, location, requestState) { if (isForbidden(location.hostname)) { @@ -107,6 +109,20 @@ function proxyRequest(req, res, proxy, location, requestState) { var locationHeader = response.headers['location']; if (locationHeader) { locationHeader = url.resolve(location.full_url, locationHeader); + + if (statusCode === 301 || statusCode === 302 || statusCode === 303) { + // Exclude 307 & 308, because they are rare, and require preserving the method + request body + requestState.redirectCount_ = requestState.requestState_ + 1 || 1; + if (requestState.redirectCount_ <= requestState.maxRedirects) { + req.method = 'GET'; + proxyRequest(req, res, proxy, parseURL(locationHeader), requestState); + + response.end(); + // The proxyResponse event is wrapped in a try-catch, throwing an error + // prevents the response from being passed to the client. + throw new Error('Prevent current response from being passed through.'); + } + } response.headers['location'] = requestState.proxyBaseUrl + '/' + locationHeader; } } @@ -127,6 +143,9 @@ function proxyRequest(req, res, proxy, location, requestState) { https: location.isHttps } }); + if (requestState.redirectCount_) { + req.emit('end'); + } } @@ -164,6 +183,7 @@ function parseURL(req_url) { // Request handler factory var getHandler = exports.getHandler = function(options) { var corsAnywhere = { + maxRedirects: 5, // Maximum number of redirects to be followed. requireHeader: null, // Require a header to be set? removeHeaders: [] // Strip these request headers }; @@ -246,6 +266,7 @@ var getHandler = exports.getHandler = function(options) { }); proxyRequest(req, res, proxy, location, { + maxRedirects: corsAnywhere.maxRedirects, proxyBaseUrl: proxyBaseUrl }); };