diff --git a/lib/cors-anywhere.js b/lib/cors-anywhere.js index e4c722a2..97e7b3b5 100644 --- a/lib/cors-anywhere.js +++ b/lib/cors-anywhere.js @@ -101,7 +101,18 @@ function proxyRequest(req, res, proxy) { } return proxyReqOn.call(this, 'response', function(proxyRes) { if (onProxyResponse(proxy, proxyReq, proxyRes, req, res)) { - listener(proxyRes); + try { + listener(proxyRes); + } catch (err) { + // Wrap in try-catch because an error could occur: + // "RangeError: Invalid status code: 0" + // https://github.com/Rob--W/cors-anywhere/issues/95 + // https://github.com/nodejitsu/node-http-proxy/issues/1080 + + // Forward error (will ultimately emit the 'error' event on our proxy object): + // https://github.com/nodejitsu/node-http-proxy/blob/v1.11.1/lib/http-proxy/passes/web-incoming.js#L134 + proxyReq.emit('error', err); + } } }); }; @@ -400,6 +411,14 @@ exports.createServer = function createServer(options) { // the headers because it would generate an error. return; } + + // When the error occurs after setting headers but before writing the response, + // then any previously set headers must be removed. + var headerNames = res.getHeaderNames ? res.getHeaderNames() : Object.keys(res._headers); + headerNames.forEach(function(name) { + res.removeHeader(name); + }); + res.writeHead(404, {'Access-Control-Allow-Origin': '*'}); res.end('Not found because of proxy error: ' + err); }); diff --git a/test/test.js b/test/test.js index 8ea28709..4c7bcd97 100644 --- a/test/test.js +++ b/test/test.js @@ -332,6 +332,28 @@ describe('Proxy errors', function() { }); }); + var bad_status_http_server; + var bad_status_http_server_url; + before(function() { + bad_status_http_server = require('net').createServer(function(socket) { + socket.setEncoding('utf-8'); + socket.on('data', function(data) { + if (data.indexOf('\r\n') >= 0) { + // Assume end of headers. + socket.write('HTTP/1.0 0\r\n'); + socket.write('Content-Length: 0\r\n'); + socket.end('\r\n'); + } + }); + }); + bad_status_http_server_url = 'http://127.0.0.1:' + bad_status_http_server.listen(0).address().port; + }); + after(function(done) { + bad_status_http_server.close(function() { + done(); + }); + }); + var bad_tcp_server; var bad_tcp_server_url; before(function() { @@ -369,6 +391,13 @@ describe('Proxy errors', function() { .expect(404, 'Not found because of proxy error: Error: Parse Error', done); }); + it('Invalid HTTP status code', function(done) { + request(cors_anywhere) + .get('/' + bad_status_http_server_url) + .expect('Access-Control-Allow-Origin', '*') + .expect(404, 'Not found because of proxy error: RangeError: Invalid status code: 0', done); + }); + it('Content-Encoding invalid body', function(done) { // The HTTP status can't be changed because the headers have already been // sent.