Socket
Socket
Sign inDemoInstall

websocket-driver

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

websocket-driver - npm Package Compare versions

Comparing version 0.1.0 to 0.2.0

CHANGELOG.md

35

lib/websocket/driver.js

@@ -7,22 +7,6 @@ // Protocol references:

var Draft75 = require('./driver/draft75'),
Draft76 = require('./driver/draft76'),
Hybi = require('./driver/hybi'),
Client = require('./driver/client');
var Client = require('./driver/client'),
Server = require('./driver/server');
var Driver = {
isSecureRequest: function(request) {
if (request.headers['x-forwarded-proto']) {
return request.headers['x-forwarded-proto'] === 'https';
} else {
return (request.connection && request.connection.authorized !== undefined) ||
(request.socket && request.socket.secure);
}
},
determineUrl: function(request) {
var scheme = this.isSecureRequest(request) ? 'wss:' : 'ws:';
return scheme + '//' + request.headers.host + request.url;
},
client: function(url, options) {

@@ -34,15 +18,10 @@ options = options || {};

http: function(request, options) {
server: function(options) {
options = options || {};
if (options.requireMasking === undefined) options.requireMasking = true;
return new Server(options);
},
var headers = request.headers,
url = this.determineUrl(request);
if (headers['sec-websocket-version'])
return new Hybi(request, url, options);
else if (headers['sec-websocket-key1'])
return new Draft76(request, url, options);
else
return new Draft75(request, url, options);
http: function() {
return Server.http.apply(Server, arguments);
},

@@ -49,0 +28,0 @@

59

lib/websocket/driver/base.js
var Emitter = require('events').EventEmitter,
util = require('util'),
streams = require('../streams');
streams = require('../streams'),
Headers = require('./headers');

@@ -10,2 +11,3 @@ var Base = function(request, url, options) {

this._options = options || {};
this.__headers = new Headers();
this.__queue = [];

@@ -15,26 +17,5 @@ this.readyState = 0;

var self = this;
this.io = new streams.IO(this);
this.messages = new streams.Messages(this);
// Protocol errors are informational and do not have to be handled
this.messages.on('error', function() {});
this.on('message', function(event) {
var messages = self.messages;
if (messages.readable) messages.emit('data', event.data);
});
this.on('error', function(error) {
var messages = self.messages;
if (messages.readable) messages.emit('error', error);
});
this.on('close', function() {
var messages = self.messages;
if (!messages.readable) return;
messages.readable = messages.writable = false;
messages.emit('end');
});
this._bindEventListeners();
};

@@ -46,2 +27,26 @@ util.inherits(Base, Emitter);

_bindEventListeners: function() {
var self = this;
// Protocol errors are informational and do not have to be handled
this.messages.on('error', function() {});
this.on('message', function(event) {
var messages = self.messages;
if (messages.readable) messages.emit('data', event.data);
});
this.on('error', function(error) {
var messages = self.messages;
if (messages.readable) messages.emit('error', error);
});
this.on('close', function() {
var messages = self.messages;
if (!messages.readable) return;
messages.readable = messages.writable = false;
messages.emit('end');
});
},
getState: function() {

@@ -51,2 +56,8 @@ return this.STATES[this.readyState] || null;

setHeader: function(name, value) {
if (this.readyState > 0) return false;
this.__headers.set(name, value);
return true;
},
start: function() {

@@ -100,2 +111,4 @@ if (this.readyState !== 0) return false;

Base.ConnectEvent = function() {};
Base.OpenEvent = function() {};

@@ -102,0 +115,0 @@

@@ -1,4 +0,4 @@

var HTTPParser = process.binding('http_parser').HTTPParser,
url = require('url'),
var url = require('url'),
util = require('util'),
HttpParser = require('./http_parser'),
Base = require('./base'),

@@ -14,27 +14,3 @@ Hybi = require('./hybi');

this._accept = Hybi.generateAccept(this._key);
this._http = new HTTPParser(HTTPParser.RESPONSE || 'response');
this._node = HTTPParser.RESPONSE ? 6 : 4;
this._complete = false;
this._headers = {};
var currentHeader = null,
self = this;
this._http.onHeaderField = function(b, start, length) {
currentHeader = b.toString('utf8', start, start + length);
};
this._http.onHeaderValue = function(b, start, length) {
self._headers[currentHeader] = b.toString('utf8', start, start + length);
};
this._http.onHeadersComplete = function(info) {
self._status = info.statusCode;
var headers = info.headers;
if (!headers) return;
for (var i = 0, n = headers.length; i < n; i += 2)
self._headers[headers[i]] = headers[i+1];
};
this._http.onMessageComplete = function() {
self._complete = true;
};
this._http = new HttpParser('response');
};

@@ -60,7 +36,7 @@ util.inherits(Client, Hybi);

var consumed = this._http.execute(data, 0, data.length),
offset = (this._node < 6) ? 1 : 0;
if (consumed <= data.length) this._validateHandshake();
if (consumed < data.length) this.parse(data.slice(consumed + offset));
this._http.parse(data);
if (!this._http.isComplete()) return;
this._validateHandshake();
this.parse(this._http.body);
},

@@ -82,3 +58,3 @@

return new Buffer(headers.concat('','').join('\r\n'), 'utf8');
return new Buffer(headers.concat(this.__headers.toString(), '').join('\r\n'), 'utf8');
},

@@ -94,10 +70,14 @@

_validateHandshake: function() {
if (this._status !== 101)
return this._failHandshake('Unexpected response code: ' + this._status);
this.statusCode = this._http.statusCode;
this.headers = this._http.headers;
var upgrade = this._headers.Upgrade || '',
connection = this._headers.Connection || '',
accept = this._headers['Sec-WebSocket-Accept'] || '',
protocol = this._headers['Sec-WebSocket-Protocol'] || '';
if (this._http.statusCode !== 101)
return this._failHandshake('Unexpected response code: ' + this._http.statusCode);
var headers = this._http.headers,
upgrade = headers['upgrade'] || '',
connection = headers['connection'] || '',
accept = headers['sec-websocket-accept'] || '',
protocol = headers['sec-websocket-protocol'] || '';
if (upgrade === '')

@@ -104,0 +84,0 @@ return this._failHandshake("'Upgrade' header is missing");

@@ -87,2 +87,3 @@ var Base = require('./base'),

'WebSocket-Location: ' + this.url + '\r\n' +
this.__headers.toString() +
'\r\n',

@@ -89,0 +90,0 @@ 'utf8');

@@ -56,2 +56,3 @@ var Base = require('./base'),

'Sec-WebSocket-Location: ' + this.url + '\r\n' +
this.__headers.toString() +
'\r\n',

@@ -58,0 +59,0 @@ 'binary');

@@ -242,3 +242,3 @@ var crypto = require('crypto'),

return new Buffer(headers.concat('','').join('\r\n'), 'utf8');
return new Buffer(headers.concat(this.__headers.toString(), '').join('\r\n'), 'utf8');
},

@@ -245,0 +245,0 @@

@@ -7,3 +7,3 @@ { "name" : "websocket-driver"

, "version" : "0.1.0"
, "version" : "0.2.0"
, "engines" : {"node": ">=0.4.0"}

@@ -10,0 +10,0 @@ , "main" : "./lib/websocket/driver"

@@ -46,3 +46,3 @@ # websocket-driver [![Build Status](https://travis-ci.org/faye/websocket-driver-node.png)](https://travis-ci.org/faye/websocket-driver-node)

### Server-side
### Server-side with HTTP

@@ -81,2 +81,49 @@ A Node webserver emits a special event for 'upgrade' requests, and this is

### Server-side with TCP
You can also handle WebSocket connections in a bare TCP server, if you're not
using an HTTP server and don't want to implement HTTP parsing yourself.
The driver will emit a `connect` event when a request is received, and at this
point you can detect whether it's a WebSocket and handle it as such. Here's an
example using the Node `net` module:
```js
var net = require('net'),
websocket = require('websocket-driver');
var server = net.createServer(function(connection) {
var driver = websocket.server();
driver.on('connect', function() {
if (websocket.isWebSocket(driver)) {
driver.start();
} else {
// handle other HTTP requests
}
});
driver.on('close', function() { connection.end() });
connection.on('error', function() {});
connection.pipe(driver.io);
driver.io.pipe(connection);
driver.messages.pipe(driver.messages);
});
server.listen(4180);
```
In the `connect` event, the driver gains several properties to describe the
request, similar to a Node request object, such as `method`, `url` and
`headers`. However you should remember it's not a real request object; you
cannot write data to it, it only tells you what request data we parsed from the
input.
If the request has a body, it will be in the `driver.body` buffer, but only as
much of the body as has been piped into the driver when the `connect` event
fires.
### Client-side

@@ -108,3 +155,9 @@

Client drivers have two additional properties for reading the HTTP data that
was sent back by the server:
* `driver.statusCode` - the integer value of the HTTP status code
* `driver.headers` - an object containing the response headers
### Driver API

@@ -116,2 +169,3 @@

driver = websocket.http(request, options)
driver = websocket.server(options)
driver = websocket.client(url, options)

@@ -121,4 +175,6 @@ ```

The `http` method returns a driver chosen using the headers from a Node HTTP
request object. The `client` method always returns a driver for the RFC version
of the protocol with masking enabled on outgoing frames.
request object. The `server` method returns a driver that will parse an HTTP
request and then decide which driver to use for it using the `http` method. The
`client` method always returns a driver for the RFC version of the protocol
with masking enabled on outgoing frames.

@@ -172,2 +228,8 @@ The `options` argument is optional, and is an object. It may contain the

#### `driver.setHeader(name, value)`
Sets a custom header to be sent as part of the handshake response, either from
the server or from the client. Must be called before `start()`, since this is
when the headers are serialized and sent.
#### `driver.start()`

@@ -174,0 +236,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc