[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)
This commit is contained in:
Rob Wu
2013-08-28 18:49:51 +02:00
parent de0318bc4c
commit 96d237e7b3

View File

@@ -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
});
};