From 828dbebcaaf11e338a7727bf9d2fff8bfbd3726e Mon Sep 17 00:00:00 2001 From: indexzero Date: Sun, 22 Jul 2012 01:03:41 -0400 Subject: [PATCH] [refactor test] Add support for `http*-to-http*` testing from CLI arguments --- package.json | 8 ++-- test/helpers/http.js | 36 +++++++++++++++--- test/helpers/index.js | 67 +++++++++++++++++++++++++++++++++ test/http/http-test.js | 4 +- test/http/routing-table-test.js | 5 ++- test/macros/http.js | 35 +++++++++++------ 6 files changed, 131 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 77a75369c..6a5d4da2b 100644 --- a/package.json +++ b/package.json @@ -18,12 +18,12 @@ ], "dependencies": { "colors": "0.x.x", - "optimist": "0.2.x", + "optimist": "0.3.x", "pkginfo": "0.2.x" }, "devDependencies": { "request": "1.9.x", - "vows": "0.5.x", + "vows": "0.6.x", "async": "0.1.x", "socket.io": "0.9.6", "socket.io-client": "0.9.6", @@ -35,8 +35,8 @@ }, "scripts": { "test": "npm run-script test-http && npm run-script test-https && npm run-script test-core", - "test-http": "vows --spec && vows --spec --target=secure", - "test-https": "vows --spec --source=secure && vows --spec --source=secure --target=secure", + "test-http": "vows --spec && vows --spec --target=https", + "test-https": "vows --spec --proxy=https && vows --spec --proxy=https --target=https", "test-core": "test/core/run" }, "engines": { diff --git a/test/helpers/http.js b/test/helpers/http.js index 063403bed..f48be88d3 100644 --- a/test/helpers/http.js +++ b/test/helpers/http.js @@ -8,9 +8,11 @@ var assert = require('assert'), http = require('http'), + https = require('https'), url = require('url'), async = require('async'), helpers = require('./index'), + protocols = helpers.protocols, httpProxy = require('../../lib/node-http-proxy'); // @@ -48,7 +50,11 @@ exports.createServerPair = function (options, callback) { // Creates a target server that the tests will proxy to. // exports.createServer = function (options, callback) { - http.createServer(function (req, res) { + // + // Request handler to use in either `http` + // or `https` server. + // + function requestHandler(req, res) { if (options.headers) { Object.keys(options.headers).forEach(function (key) { assert.equal(req.headers[key], options.headers[key]); @@ -58,7 +64,13 @@ exports.createServer = function (options, callback) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write(options.output || 'hello proxy'); res.end(); - }).listen(options.port, function () { + } + + var server = protocols.target === 'https' + ? https.createServer(helpers.https, requestHandler) + : http.createServer(requestHandler); + + server.listen(options.port, function () { callback(null, this); }); }; @@ -76,6 +88,10 @@ exports.createServer = function (options, callback) { // exports.createProxyServer = function (options, callback) { if (!options.latency) { + if (protocols.proxy === 'https') { + options.proxy.https = helpers.https; + } + return httpProxy .createServer(options.proxy) .listen(options.port, function () { @@ -87,9 +103,13 @@ exports.createProxyServer = function (options, callback) { ? new httpProxy.RoutingProxy(options.proxy) : new httpProxy.HttpProxy(options.proxy); - http.createServer(function (req, res) { + // + // Request handler to use in either `http` + // or `https` server. + // + function requestHandler(req, res) { var buffer = httpProxy.buffer(req); - + setTimeout(function () { // // Setup options dynamically for `RoutingProxy.prototype.proxyRequest` @@ -98,7 +118,13 @@ exports.createProxyServer = function (options, callback) { buffer = options.routing ? { buffer: buffer } : buffer proxy.proxyRequest(req, res, buffer); }, options.latency); - }).listen(options.port, function () { + } + + var server = protocols.proxy === 'https' + ? https.createServer(helpers.https, requestHandler) + : http.createServer(requestHandler); + + server.listen(options.port, function () { callback(null, this); }); }; diff --git a/test/helpers/index.js b/test/helpers/index.js index d98bdf460..a62505027 100644 --- a/test/helpers/index.js +++ b/test/helpers/index.js @@ -6,6 +6,40 @@ * */ +var fs = require('fs'), + path = require('path'); + +var fixturesDir = path.join(__dirname, '..', 'fixtures'); + +// +// @https {Object} +// Returns the necessary `https` credentials. +// +Object.defineProperty(exports, 'https', { + get: function () { + delete this.https; + return this.https = { + key: fs.readFileSync(path.join(fixturesDir, 'agent2-key.pem'), 'utf8'), + cert: fs.readFileSync(path.join(fixturesDir, 'agent2-cert.pem'), 'utf8') + }; + } +}); + +// +// @protocols {Object} +// Returns an object representing the desired protocols +// for the `proxy` and `target` server. +// +Object.defineProperty(exports, 'protocols', { + get: function () { + delete this.protocols; + return this.protocols = { + target: exports.argv.target || 'http', + proxy: exports.argv.proxy || 'http' + }; + } +}); + // // @nextPort {number} // Returns an auto-incrementing port for tests. @@ -31,6 +65,39 @@ Object.defineProperty(exports, 'nextPortPair', { } }); +// +// ### function describe(prefix) +// #### @prefix {string} Prefix to use before the description +// +// Returns a string representing the protocols that this suite +// is testing based on CLI arguments. +// +exports.describe = function (prefix, base) { + prefix = prefix || ''; + base = base || 'http' + + function protocol(endpoint) { + return exports.protocols[endpoint] === 'https' + ? base + 's' + : base; + } + + return [ + 'node-http-proxy', + prefix, + [ + protocol('proxy'), + '-to-', + protocol('target') + ].join('') + ].filter(Boolean).join('/'); +}; + +// +// Expose the CLI arguments +// +exports.argv = require('optimist').argv; + // // Export additional helpers for `http` and `websockets`. // diff --git a/test/http/http-test.js b/test/http/http-test.js index a8bfc7c88..585597c12 100644 --- a/test/http/http-test.js +++ b/test/http/http-test.js @@ -31,11 +31,11 @@ var assert = require('assert'), request = require('request'), vows = require('vows'), macros = require('../macros'), - helpers = require('../helpers/index'); + helpers = require('../helpers'); var routeFile = path.join(__dirname, 'config.json'); -vows.describe('node-http-proxy/http').addBatch({ +vows.describe(helpers.describe()).addBatch({ "With a valid target server": { "and no latency": { "and no headers": macros.http.assertProxied(), diff --git a/test/http/routing-table-test.js b/test/http/routing-table-test.js index a50caa3f9..d7119f825 100644 --- a/test/http/routing-table-test.js +++ b/test/http/routing-table-test.js @@ -16,7 +16,7 @@ var assert = require('assert'), var routeFile = path.join(__dirname, 'config.json'); -vows.describe('node-http-proxy/http/routing-table').addBatch({ +vows.describe(helpers.describe('routing-table')).addBatch({ "With a routing table": { "with latency": macros.http.assertProxiedToRoutes({ latency: 2000, @@ -53,6 +53,7 @@ vows.describe('node-http-proxy/http/routing-table').addBatch({ "after the file has been modified": { topic: function () { var config = JSON.parse(fs.readFileSync(routeFile, 'utf8')), + protocol = helpers.protocols.proxy, port = helpers.nextPort, that = this; @@ -72,7 +73,7 @@ vows.describe('node-http-proxy/http/routing-table').addBatch({ ) ], function () { request({ - uri: 'http://127.0.0.1:' + that.port, + uri: protocol + '://127.0.0.1:' + that.port, headers: { host: 'dynamic.com' } diff --git a/test/macros/http.js b/test/macros/http.js index 7a74367d3..fd07b489d 100644 --- a/test/macros/http.js +++ b/test/macros/http.js @@ -30,6 +30,7 @@ exports.assertRequest = function (options) { request(options.request, this.callback); }, "should succeed": function (err, res, body) { + assert.isNull(err); if (options.assert.body) { assert.equal(body, options.assert.body); } @@ -55,11 +56,12 @@ exports.assertRequest = function (options) { exports.assertProxied = function (options) { options = options || {}; - var ports = options.ports || helpers.nextPortPair, - output = options.output || 'hello world from ' + ports.target, - req = options.request || {}; + var ports = options.ports || helpers.nextPortPair, + output = options.output || 'hello world from ' + ports.target, + protocol = helpers.protocols.proxy, + req = options.request || {}; - req.uri = req.uri || 'http://127.0.0.1:' + ports.proxy; + req.uri = req.uri || protocol + '://127.0.0.1:' + ports.proxy; return { topic: function () { @@ -79,6 +81,7 @@ exports.assertProxied = function (options) { proxy: { forward: options.forward, target: { + https: helpers.protocols.target === 'https', host: '127.0.0.1', port: ports.target } @@ -107,10 +110,12 @@ exports.assertProxied = function (options) { exports.assertInvalidProxy = function (options) { options = options || {}; - var ports = options.ports || helpers.nextPortPair, - req = options.request || {}; + var ports = options.ports || helpers.nextPortPair, + req = options.request || {}, + protocol = helpers.protocols.proxy; - req.uri = req.uri || 'http://127.0.0.1:' + ports.proxy; + + req.uri = req.uri || protocol + '://127.0.0.1:' + ports.proxy; return { topic: function () { @@ -196,9 +201,10 @@ exports.assertProxiedToRoutes = function (options, nested) { // var locations = helpers.http.parseRoutes(options), port = helpers.nextPort, + protocol = helpers.protocols.proxy, context, proxy; - + if (options.filename) { // // If we've been passed a filename write the routes to it @@ -215,7 +221,14 @@ exports.assertProxiedToRoutes = function (options, nested) { hostnameOnly: options.hostnameOnly, router: options.routes }; - } + } + + // + // Set the https options if necessary + // + if (helpers.protocols.target === 'https') { + proxy.target = { https: true }; + } // // Create the test context which creates all target @@ -271,7 +284,7 @@ exports.assertProxiedToRoutes = function (options, nested) { "a request to unknown.com": exports.assertRequest({ assert: { statusCode: 404 }, request: { - uri: 'http://127.0.0.1:' + port, + uri: protocol + '://127.0.0.1:' + port, headers: { host: 'unknown.com' } @@ -285,7 +298,7 @@ exports.assertProxiedToRoutes = function (options, nested) { locations.forEach(function (location) { context[location.source.href] = exports.assertRequest({ request: { - uri: 'http://127.0.0.1:' + port + location.source.path, + uri: protocol + '://127.0.0.1:' + port + location.source.path, headers: { host: location.source.hostname }