2 * ws.js: Macros for proxying Websocket requests
4 * (C) 2010 Nodejitsu Inc.
9 var assert = require('assert'),
11 async = require('async'),
12 io = require('socket.io-client'),
13 WebSocket = require('ws'),
14 helpers = require('../helpers/index');
17 // ### function assertSendRecieve (options)
18 // #### @options {Object} Options for creating this assertion.
19 // #### @raw {boolean} Enables raw `ws.WebSocket`.
20 // #### @uri {string} URI of the proxy server.
21 // #### @input {string} Input to assert sent to the target ws server.
22 // #### @output {string} Output to assert from the taget ws server.
24 // Creates a `socket.io` or raw `WebSocket` connection and asserts that
25 // `options.input` is sent to and `options.output` is received from the
28 exports.assertSendReceive = function (options) {
32 var socket = io.connect(options.uri);
33 socket.on('outgoing', this.callback.bind(this, null));
34 socket.emit('incoming', options.input);
36 "should send input and receive output": function (_, data) {
37 assert.equal(data, options.output);
44 var socket = new WebSocket(options.uri);
45 socket.on('message', this.callback.bind(this, null));
46 socket.on('open', function () {
47 socket.send(options.input);
50 "should send input and recieve output": function (_, data, flags) {
51 assert.equal(data, options.output);
57 // ### function assertProxied (options)
58 // #### @options {Object} Options for this test
59 // #### @latency {number} Latency in milliseconds for the proxy server.
60 // #### @ports {Object} Ports for the request (target, proxy).
61 // #### @input {string} Input to assert sent to the target ws server.
62 // #### @output {string} Output to assert from the taget ws server.
63 // #### @raw {boolean} Enables raw `ws.Server` usage.
65 // Creates a complete end-to-end test for requesting against an
68 exports.assertProxied = function (options) {
69 options = options || {};
71 var ports = options.ports || helpers.nextPortPair,
72 input = options.input || 'hello world to ' + ports.target,
73 output = options.output || 'hello world from ' + ports.target,
74 protocol = helpers.protocols.proxy;
77 protocol = helpers.protocols.proxy === 'https'
84 helpers.ws.createServerPair({
92 latency: options.latency,
96 https: helpers.protocols.target === 'https',
104 "the proxy Websocket connection": exports.assertSendReceive({
105 uri: protocol + '://127.0.0.1:' + ports.proxy,
114 // ### function assertProxiedtoRoutes (options, nested)
115 // #### @options {Object} Options for this ProxyTable-based test
116 // #### @raw {boolean} Enables ws.Server usage.
117 // #### @routes {Object|string} Routes to use for the proxy.
118 // #### @hostnameOnly {boolean} Enables hostnameOnly routing.
119 // #### @nested {Object} Nested vows to add to the returned context.
121 // Creates a complete end-to-end test for requesting against an
122 // http proxy using `options.routes`:
124 // 1. Creates target servers for all routes in `options.routes.`
125 // 2. Creates a proxy server.
126 // 3. Ensure Websocket connections to the proxy server for all route targets
127 // can send input and recieve output.
129 exports.assertProxiedToRoutes = function (options, nested) {
131 // Assign dynamic ports to the routes to use.
133 options.routes = helpers.http.assignPortsToRoutes(options.routes);
136 // Parse locations from routes for making assertion requests.
138 var locations = helpers.http.parseRoutes(options),
139 protocol = helpers.protocols.proxy,
140 port = helpers.nextPort,
145 protocol = helpers.protocols.proxy === 'https'
150 if (options.filename) {
152 // If we've been passed a filename write the routes to it
153 // and setup the proxy options to use that file.
155 fs.writeFileSync(options.filename, JSON.stringify({ router: options.routes }));
156 proxy = { router: options.filename };
160 // Otherwise just use the routes themselves.
163 hostnameOnly: options.hostnameOnly,
164 router: options.routes
169 // Create the test context which creates all target
170 // servers for all routes and a proxy server.
178 // 1. Create all the target servers
183 function createRouteTarget(location, next) {
184 helpers.ws.createServer({
186 port: location.target.port,
187 output: 'hello from ' + location.source.href,
188 input: 'hello to ' + location.source.href
193 // 2. Create the proxy server
196 helpers.http.createProxyServer,
199 latency: options.latency,
204 ], function (_, server) {
206 // 3. Set the proxy server for later use
208 that.proxyServer = server;
213 // 4. Assign the port to the context for later use
220 // Add test assertions for each of the route locations.
222 locations.forEach(function (location) {
223 context[location.source.href] = exports.assertSendRecieve({
224 uri: protocol + '://127.0.0.1:' + port + location.source.path,
225 output: 'hello from ' + location.source.href,
226 input: 'hello to ' + location.source.href,