Upgrade from http-proxy 0.10.x to 1.3.0

This commit is contained in:
Rob Wu
2014-08-25 13:39:25 +02:00
parent beadd3fe77
commit bd9af5849f
3 changed files with 45 additions and 54 deletions

View File

@@ -1,9 +1,10 @@
// © 2013 Rob W <gwnRob@gmail.com>
// © 2013 - 2014 Rob Wu <rob@robwu.nl>
// Released under the MIT license
'use strict';
/* jshint node:true, eqnull:true, sub:true, quotmark:single, unused:true */
var http = require('http');
var httpProxy = require('http-proxy');
var net = require('net');
var url = require('url');
@@ -37,7 +38,7 @@ function showUsage(headers, response) {
* @return {boolean} Whether the requested resource can be accessed.
*/
function isValidHostName(hostname) {
return !(
return !!(
regexp_tld.test(hostname) ||
net.isIPv4(hostname) ||
net.isIPv6(hostname)
@@ -85,24 +86,20 @@ function proxyRequest(req, res, proxy) {
req.headers.host = location.host;
// Start proxying the request
proxy.proxyRequest(req, res, {
host: location.hostname,
port: location.port,
target: {
https: location.isHttps
}
proxy.web(req, res, {
target: location
});
}
/**
* "Allow observer to modify headers or abort response"
* https://github.com/nodejitsu/node-http-proxy/blob/ebbba73e/lib/node-http-proxy/http-proxy.js#L321-L322
* https://github.com/nodejitsu/node-http-proxy/blob/05f0b891/lib/http-proxy/passes/web-incoming.js#L147
*
* This method modifies the response headers of the proxied response.
* If a redirect is detected, the response is not sent to the client,
* and a new request is initiated.
*
* @param response {ClientRequest} The response of the proxied request
* @param req {IncomingMessage} Incoming HTTP request, augmented with property corsAnywhereRequestState
* @param req.corsAnywhereRequestState {object}
* @param req.corsAnywhereRequestState.location {object} See parseURL
@@ -110,11 +107,10 @@ function proxyRequest(req, res, proxy) {
* @param req.corsAnywhereRequestState.maxRedirects {number} Maximum number of redirects
* @param req.corsAnywhereRequestState.redirectCount_ {number} Internally used to count redirects
* @param res {ServerResponse} Outgoing (proxied) HTTP request
* @param response {ClientRequest} The
*
* @this {HttpProxy}
*/
function onProxyResponse(req, res, response) {
function onProxyResponse(response, req, res) {
/* jshint validthis:true */
var proxy = this;
var requestState = req.corsAnywhereRequestState;
@@ -145,28 +141,25 @@ function onProxyResponse(req, res, response) {
requestState.location = parseURL(locationHeader);
// ### Dispose the current proxied request
// Verified assumption: When proxy.proxyRequest is called for the first time,
// there are no event listeners on the "req" object.
// First remove the "end" event, to avoid the req.end() call by node-http-proxy/http-proxy
// https://github.com/nodejitsu/node-http-proxy/blob/ebbba73e/lib/node-http-proxy/http-proxy.js#L310-319
response.removeAllListeners('end');
// Trigger disposal of the reverseProxy
// https://github.com/nodejitsu/node-http-proxy/blob/ebbba73e/lib/node-http-proxy/http-proxy.js#L375-L378
req.emit('aborted');
// Remove all listeners (=events reset to initial state)
req.removeAllListeners();
// Initiate a new proxy request.
proxyRequest(req, res, proxy);
// Trigger reverseProxy.end() to initiate the proxy
// The event listener is added at the end of HttpProxy.prototype.proxyRequest, synchronously.
// https://github.com/nodejitsu/node-http-proxy/blob/ebbba73e/lib/node-http-proxy/http-proxy.js#L407-L415
req.emit('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.');
// Haha - hack! This should be fixed when (if?) node-http-proxy supports cancelation of requests..
// Shadow all methods that mutate the |res| object.
// See https://github.com/nodejitsu/node-http-proxy/blob/05f0b891/lib/http-proxy/passes/web-outgoing.js
var setHeader = res.setHeader;
var writeHead = res.writeHead;
res.setHeader = res.writeHead = function noop() {};
response.on = function noop2() {};
response.pipe = function(res) {
res.setHeader = setHeader;
res.writeHead = writeHead;
// Trigger proxyReq.abort() (this is not of any imporance, it's just used to stop wasting resources.)
// https://github.com/nodejitsu/node-http-proxy/blob/05f0b891/lib/http-proxy/passes/web-incoming.js#L125-L128
req.emit('aborted');
// Remove all listeners (=reset events to initial state)
req.removeAllListeners();
// Initiate a new proxy request.
proxyRequest(req, res, proxy);
};
return;
}
}
response.headers['location'] = requestState.proxyBaseUrl + '/' + locationHeader;
@@ -214,7 +207,7 @@ function parseURL(req_url) {
}
// Request handler factory
var getHandler = exports.getHandler = function(options) {
var getHandler = exports.getHandler = function(options, proxy) {
var corsAnywhere = {
maxRedirects: 5, // Maximum number of redirects to be followed.
requireHeader: null, // Require a header to be set?
@@ -245,7 +238,7 @@ var getHandler = exports.getHandler = function(options) {
});
};
return function(req, res, proxy) {
return function(req, res) {
var cors_headers = withCORS({}, req);
if (req.method == 'OPTIONS') {
// Pre-flight request. Reply successfully:
@@ -278,7 +271,7 @@ var getHandler = exports.getHandler = function(options) {
return;
}
if (isValidHostName(location.hostname)) {
if (!isValidHostName(location.hostname)) {
// Don't even try to proxy invalid hosts (such as /favicon.ico, /robots.txt)
res.writeHead(404, 'Invalid host', cors_headers);
res.end('Invalid host: ' + location.hostname);
@@ -305,11 +298,6 @@ var getHandler = exports.getHandler = function(options) {
proxyBaseUrl: proxyBaseUrl
};
if (!proxy.hasCorsAnywhereResponseHandler) { // Runs once per HttpProxy instance
proxy.on('proxyResponse', onProxyResponse);
proxy.hasCorsAnywhereResponseHandler = true;
}
proxyRequest(req, res, proxy);
};
};
@@ -321,9 +309,7 @@ exports.createServer = function createServer(options) {
// Default options:
var httpProxyOptions = {
xforward: {
enable: true // Append X-Forwarded-* headers
}
xfwd: true, // Append X-Forwarded-* headers
};
// Allow user to override defaults and add own options
if (options.httpProxyOptions) {
@@ -332,14 +318,21 @@ exports.createServer = function createServer(options) {
});
}
var handler = getHandler(options);
var server = httpProxy.createServer(httpProxyOptions, handler);
var proxy = httpProxy.createServer(httpProxyOptions);
var server = http.createServer(getHandler(options, proxy));
// When the server fails, just show a 404 instead of Internal server error
server.proxy.on('proxyError', function(err, req, res) {
proxy.on('error', function(err, req, res) {
if (res._headerSent) {
// E.g. when the server replies with an invalid Content-Length value,
// causing the response to end as expected while triggering the
// "HPE_INVALID_CONSTANT" error.
return;
}
res.writeHead(404, {'Access-Control-Allow-Origin': '*'});
res.end('Not found because of proxy error: ' + err);
});
proxy.on('proxyRes', onProxyResponse);
return server;
};

View File

@@ -3,7 +3,7 @@
"version": "0.1.9",
"description": "CORS Anywhere is a reverse proxy which adds CORS headers to the proxied request. Request URL is taken from the path",
"license": "MIT",
"author": "Rob Wu <gwnRob@gmail.com>",
"author": "Rob Wu <rob@robwu.nl>",
"repository": {
"type": "git",
"url": "https://github.com/Rob--W/cors-anywhere.git"
@@ -21,7 +21,7 @@
],
"main": "./lib/cors-anywhere.js",
"dependencies": {
"http-proxy": "~0.10"
"http-proxy": "1.3.0"
},
"devDependencies": {
"webkit-devtools-agent": "~0.2.1"

View File

@@ -15,10 +15,8 @@ cors_proxy.createServer({
'x-request-start'
],
httpProxyOptions: {
enable: {
// Do not add X-Forwarded-For, etc. headers, because Heroku already adds it.
xforward: false
}
// Do not add X-Forwarded-For, etc. headers, because Heroku already adds it.
xfwd: false
}
}).listen(port, host, function() {
console.log('Running CORS Anywhere on ' + host + ':' + port);