4 * ws: a node.js websocket client
5 * Copyright(c) 2011 Einar Otto Stangvik <einaros@gmail.com>
10 * Module dependencies.
13 var WebSocket = require('../')
15 , program = require('commander')
16 , util = require('util')
17 , events = require('events')
18 , readline = require('readline');
21 * InputReader - processes console input
25 this.stdin = process.stdin;
26 this.stdout = process.stdout;
28 this.readlineInterface = readline.createInterface(this.stdin, this.stdout);
31 this.readlineInterface.on('line', function(data) {
32 self.emit('line', data);
34 this.readlineInterface.on('close', function() {
38 this._resetInput = function() {
42 util.inherits(Console, events.EventEmitter);
52 Console.prototype.prompt = function() {
53 this.readlineInterface.prompt();
56 Console.prototype.print = function(msg, color) {
58 color = color || Console.Colors.Default;
59 this.stdout.write(color + msg + Console.Colors.Default + '\n');
63 Console.prototype.clear = function() {
64 this.stdout.write('\033[2K\033[E');
67 Console.prototype.pause = function() {
68 this.stdin.on('keypress', this._resetInput);
71 Console.prototype.resume = function() {
72 this.stdin.removeListener('keypress', this._resetInput);
75 function appender(xs) {
83 function into(obj, kvals) {
84 kvals.forEach(function (kv) {
90 function splitOnce(sep, str) { // sep can be either String or RegExp
91 var tokens = str.split(sep);
92 return [tokens[0], str.replace(sep, '').substr(tokens[0].length)];
96 * The actual application
99 var version = JSON.parse(fs.readFileSync(__dirname + '/../package.json', 'utf8')).version;
102 .usage('[options] <url>')
103 .option('-l, --listen <port>', 'listen on port')
104 .option('-c, --connect <url>', 'connect to a websocket server')
105 .option('-p, --protocol <version>', 'optional protocol version')
106 .option('-o, --origin <origin>', 'optional origin')
107 .option('--host <host>', 'optional host')
108 .option('-s, --subprotocol <protocol>', 'optional subprotocol')
109 .option('-n, --no-check', 'Do not check for unauthorized certificates')
110 .option('-H, --header <header:value>', 'Set an HTTP header. Repeat to set multiple. (--connect only)', appender(), [])
111 .option('--auth <username:password>', 'Add basic HTTP authentication header. (--connect only)')
112 .parse(process.argv);
114 if (program.listen && program.connect) {
115 console.error('\033[33merror: use either --listen or --connect\033[39m');
118 else if (program.listen) {
119 var wsConsole = new Console();
122 if (program.protocol) options.protocolVersion = program.protocol;
123 if (program.origin) options.origin = program.origin;
124 if (program.subprotocol) options.protocol = program.subprotocol;
125 if (!program.check) options.rejectUnauthorized = program.check;
127 var wss = new WebSocket.Server({port: program.listen}, function() {
128 wsConsole.print('listening on port ' + program.listen + ' (press CTRL+C to quit)', Console.Colors.Green);
131 wsConsole.on('close', function() {
140 wsConsole.on('line', function(data) {
142 ws.send(data, {mask: false});
146 wss.on('connection', function(newClient) {
148 // limit to one client
149 newClient.terminate();
155 wsConsole.print('client connected', Console.Colors.Green);
156 ws.on('close', function() {
157 wsConsole.print('disconnected', Console.Colors.Green);
162 ws.on('error', function(code, description) {
163 wsConsole.print('error: ' + code + (description ? ' ' + description : ''), Console.Colors.Yellow);
165 ws.on('message', function(data, flags) {
166 wsConsole.print('< ' + data, Console.Colors.Blue);
169 wss.on('error', function(error) {
170 wsConsole.print('error: ' + error.toString(), Console.Colors.Yellow);
174 else if (program.connect) {
175 var wsConsole = new Console();
177 if (program.protocol) options.protocolVersion = program.protocol;
178 if (program.origin) options.origin = program.origin;
179 if (program.subprotocol) options.protocol = program.subprotocol;
180 if (program.host) options.host = program.host;
181 if (!program.check) options.rejectUnauthorized = program.check;
182 var headers = into({}, (program.header || []).map(function (s) {
183 return splitOnce(':', s)
186 headers['Authorization'] = 'Basic ' + new Buffer(program.auth).toString('base64');
188 options.headers = headers;
189 var ws = new WebSocket(program.connect, options);
190 ws.on('open', function() {
191 wsConsole.print('connected (press CTRL+C to quit)', Console.Colors.Green);
192 wsConsole.on('line', function(data) {
193 ws.send(data, {mask: true});
197 ws.on('close', function() {
198 wsConsole.print('disconnected', Console.Colors.Green);
202 ws.on('error', function(code, description) {
203 wsConsole.print('error: ' + code + (description ? ' ' + description : ''), Console.Colors.Yellow);
206 ws.on('message', function(data, flags) {
207 wsConsole.print('< ' + data, Console.Colors.Blue);
209 wsConsole.on('close', function() {
220 console.error('\033[33merror: use either --listen or --connect\033[39m');