From c37e496dee41349c0601f6f08e432cdb2e2eb939 Mon Sep 17 00:00:00 2001 From: Rob Wu Date: Wed, 28 Aug 2013 12:10:08 +0200 Subject: [PATCH] Add extra documentation (in code). Removed ? from path's regexp, because "http://cors-anywhere/" + "/domain.com/file" = "http://cors-anywhere//domain.com/file" SHOULD be an invalid request. "//domain.com/file" can be resolved to "http://domain.com/file", but "/domain.com/file" should resolved to http://host/domain.com/file, but since the host is unknown, the API should just fail. --- lib/cors-anywhere.js | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/lib/cors-anywhere.js b/lib/cors-anywhere.js index 030ec1d..0fd6941 100644 --- a/lib/cors-anywhere.js +++ b/lib/cors-anywhere.js @@ -30,8 +30,13 @@ function showUsage(headers, response) { } } +/** + * Check whether the specified hostname is valid. + * + * @param hostname {string} Host name (excluding port) of requested resource. + * @return {boolean} Whether the requested resource can be accessed. + */ function hasNoContent(hostname) { - // Show 404 for non-requests. For instance when hostname is favicon.ico, robots.txt, ... return !( regexp_tld.test(hostname) || net.isIPv4(hostname) || @@ -39,8 +44,12 @@ function hasNoContent(hostname) { ); } -// First argument: The response.headers object -// Second argument: The request object. +/** + * Adds CORS headers to the response headers. + * + * @param headers {object} Response headers + * @param request {ServerRequest} + */ function withCORS(headers, request) { var origin = request.headers.origin || 'null'; headers['access-control-allow-origin'] = origin === 'null' ? '*' : origin; @@ -61,9 +70,23 @@ function withCORS(headers, request) { return headers; } + +/** + * @param host {string} Host name (excluding port) of requested resource + */ function isForbidden(host) { return false; // TODO } + +/** + * Performs the actual proxy request. + * + * @param req {ServerRequest} Incoming http request + * @param res {ServerResponse} Outgoing (proxied) http request + * @param proxy {HttpProxy} + * @param full_url {string} Canonical URL of outgoing (proxied) http request. + * @param isRequestedOverHttps {boolean} Whether the incoming request originates from https + */ function proxyRequest(req, res, proxy, full_url, isRequestedOverHttps, proxyOptions) { if (isForbidden(proxyOptions.host)) { res.writeHead(403, 'Refused to visit', withCORS({'Location': full_url}, req)); @@ -142,7 +165,7 @@ var getHandler = exports.getHandler = function(options) { } else { // Actual request. First, extract the desired URL from the request: var full_url, host, hostname, port, path, match, isHttps; - match = req.url.match(/^\/?(?:(https?:)?\/\/)?(([^\/?]+?)(?::(\d{0,5})(?=[\/?]|$))?)([\/?][\S\s]*|$)/i); + match = req.url.match(/^\/(?:(https?:)?\/\/)?(([^\/?]+?)(?::(\d{0,5})(?=[\/?]|$))?)([\/?][\S\s]*|$)/i); // ^^^^^^^ ^^^^^^^^ ^^^^^^^ ^^^^^^^^^^^^ // 1:protocol 3:hostname 4:port 5:path + query string // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -162,12 +185,12 @@ var getHandler = exports.getHandler = function(options) { } else if (match[4] > 65535) { // Port is higher than 65535 res.writeHead(400, 'Invalid port', cors_headers); - res.end(); + res.end('Invalid port: ' + match[4]); return; } else if ( hasNoContent(match[3]) ) { - // Don't even try to proxy invalid hosts + // Don't even try to proxy invalid hosts (such as /favicon.ico, /robots.txt) res.writeHead(404, 'Invalid host', cors_headers); - res.end(); + res.end('Invalid host: ' + match[3]); return; } else if (!hasRequiredHeaders(req.headers)) { res.writeHead(400, 'Header required', cors_headers);