mirror of
https://github.com/http-party/node-http-proxy.git
synced 2025-12-08 20:59:18 +00:00
232 lines
6.5 KiB
JavaScript
232 lines
6.5 KiB
JavaScript
/*
|
|
* ws.js: Macros for proxying Websocket requests
|
|
*
|
|
* (C) 2010 Nodejitsu Inc.
|
|
* MIT LICENCE
|
|
*
|
|
*/
|
|
|
|
var assert = require('assert'),
|
|
fs = require('fs'),
|
|
async = require('async'),
|
|
io = require('socket.io-client'),
|
|
WebSocket = require('ws'),
|
|
helpers = require('../helpers/index');
|
|
|
|
//
|
|
// ### function assertSendRecieve (options)
|
|
// #### @options {Object} Options for creating this assertion.
|
|
// #### @raw {boolean} Enables raw `ws.WebSocket`.
|
|
// #### @uri {string} URI of the proxy server.
|
|
// #### @input {string} Input to assert sent to the target ws server.
|
|
// #### @output {string} Output to assert from the taget ws server.
|
|
//
|
|
// Creates a `socket.io` or raw `WebSocket` connection and asserts that
|
|
// `options.input` is sent to and `options.output` is received from the
|
|
// connection.
|
|
//
|
|
exports.assertSendReceive = function (options) {
|
|
if (!options.raw) {
|
|
return {
|
|
topic: function () {
|
|
var socket = io.connect(options.uri);
|
|
socket.on('outgoing', this.callback.bind(this, null));
|
|
socket.emit('incoming', options.input);
|
|
},
|
|
"should send input and receive output": function (_, data) {
|
|
assert.equal(data, options.output);
|
|
}
|
|
};
|
|
}
|
|
|
|
return {
|
|
topic: function () {
|
|
var socket = new WebSocket(options.uri);
|
|
socket.on('message', this.callback.bind(this, null));
|
|
socket.on('open', function () {
|
|
socket.send(options.input);
|
|
});
|
|
},
|
|
"should send input and recieve output": function (_, data, flags) {
|
|
assert.equal(data, options.output);
|
|
}
|
|
};
|
|
};
|
|
|
|
//
|
|
// ### function assertProxied (options)
|
|
// #### @options {Object} Options for this test
|
|
// #### @latency {number} Latency in milliseconds for the proxy server.
|
|
// #### @ports {Object} Ports for the request (target, proxy).
|
|
// #### @input {string} Input to assert sent to the target ws server.
|
|
// #### @output {string} Output to assert from the taget ws server.
|
|
// #### @raw {boolean} Enables raw `ws.Server` usage.
|
|
//
|
|
// Creates a complete end-to-end test for requesting against an
|
|
// http proxy.
|
|
//
|
|
exports.assertProxied = function (options) {
|
|
options = options || {};
|
|
|
|
var ports = options.ports || helpers.nextPortPair,
|
|
input = options.input || 'hello world to ' + ports.target,
|
|
output = options.output || 'hello world from ' + ports.target,
|
|
protocol = helpers.protocols.proxy;
|
|
|
|
if (options.raw) {
|
|
protocol = helpers.protocols.proxy === 'https'
|
|
? 'wss'
|
|
: 'ws';
|
|
}
|
|
|
|
return {
|
|
topic: function () {
|
|
helpers.ws.createServerPair({
|
|
target: {
|
|
input: input,
|
|
output: output,
|
|
port: ports.target,
|
|
raw: options.raw
|
|
},
|
|
proxy: {
|
|
latency: options.latency,
|
|
port: ports.proxy,
|
|
proxy: {
|
|
target: {
|
|
https: helpers.protocols.target === 'https',
|
|
host: '127.0.0.1',
|
|
port: ports.target
|
|
}
|
|
}
|
|
}
|
|
}, this.callback);
|
|
},
|
|
"the proxy Websocket connection": exports.assertSendReceive({
|
|
uri: protocol + '://127.0.0.1:' + ports.proxy,
|
|
input: input,
|
|
output: output,
|
|
raw: options.raw
|
|
})
|
|
};
|
|
};
|
|
|
|
//
|
|
// ### function assertProxiedtoRoutes (options, nested)
|
|
// #### @options {Object} Options for this ProxyTable-based test
|
|
// #### @raw {boolean} Enables ws.Server usage.
|
|
// #### @routes {Object|string} Routes to use for the proxy.
|
|
// #### @hostnameOnly {boolean} Enables hostnameOnly routing.
|
|
// #### @nested {Object} Nested vows to add to the returned context.
|
|
//
|
|
// Creates a complete end-to-end test for requesting against an
|
|
// http proxy using `options.routes`:
|
|
//
|
|
// 1. Creates target servers for all routes in `options.routes.`
|
|
// 2. Creates a proxy server.
|
|
// 3. Ensure Websocket connections to the proxy server for all route targets
|
|
// can send input and recieve output.
|
|
//
|
|
exports.assertProxiedToRoutes = function (options, nested) {
|
|
//
|
|
// Assign dynamic ports to the routes to use.
|
|
//
|
|
options.routes = helpers.http.assignPortsToRoutes(options.routes);
|
|
|
|
//
|
|
// Parse locations from routes for making assertion requests.
|
|
//
|
|
var locations = helpers.http.parseRoutes(options),
|
|
protocol = helpers.protocols.proxy,
|
|
port = helpers.nextPort,
|
|
context,
|
|
proxy;
|
|
|
|
if (options.raw) {
|
|
protocol = helpers.protocols.proxy === 'https'
|
|
? 'wss'
|
|
: 'ws';
|
|
}
|
|
|
|
if (options.filename) {
|
|
//
|
|
// If we've been passed a filename write the routes to it
|
|
// and setup the proxy options to use that file.
|
|
//
|
|
fs.writeFileSync(options.filename, JSON.stringify({ router: options.routes }));
|
|
proxy = { router: options.filename };
|
|
}
|
|
else {
|
|
//
|
|
// Otherwise just use the routes themselves.
|
|
//
|
|
proxy = {
|
|
hostnameOnly: options.hostnameOnly,
|
|
router: options.routes
|
|
};
|
|
}
|
|
|
|
//
|
|
// Create the test context which creates all target
|
|
// servers for all routes and a proxy server.
|
|
//
|
|
context = {
|
|
topic: function () {
|
|
var that = this;
|
|
|
|
async.waterfall([
|
|
//
|
|
// 1. Create all the target servers
|
|
//
|
|
async.apply(
|
|
async.forEach,
|
|
locations,
|
|
function createRouteTarget(location, next) {
|
|
helpers.ws.createServer({
|
|
raw: options.raw,
|
|
port: location.target.port,
|
|
output: 'hello from ' + location.source.href,
|
|
input: 'hello to ' + location.source.href
|
|
}, next);
|
|
}
|
|
),
|
|
//
|
|
// 2. Create the proxy server
|
|
//
|
|
async.apply(
|
|
helpers.http.createProxyServer,
|
|
{
|
|
port: port,
|
|
latency: options.latency,
|
|
routing: true,
|
|
proxy: proxy
|
|
}
|
|
)
|
|
], function (_, server) {
|
|
//
|
|
// 3. Set the proxy server for later use
|
|
//
|
|
that.proxyServer = server;
|
|
that.callback();
|
|
});
|
|
|
|
//
|
|
// 4. Assign the port to the context for later use
|
|
//
|
|
this.port = port;
|
|
}
|
|
};
|
|
|
|
//
|
|
// Add test assertions for each of the route locations.
|
|
//
|
|
locations.forEach(function (location) {
|
|
context[location.source.href] = exports.assertSendRecieve({
|
|
uri: protocol + '://127.0.0.1:' + port + location.source.path,
|
|
output: 'hello from ' + location.source.href,
|
|
input: 'hello to ' + location.source.href,
|
|
raw: options.raw
|
|
});
|
|
});
|
|
|
|
return context;
|
|
}; |