websocket-driver
Advanced tools
Comparing version 0.3.6 to 0.4.0
@@ -0,1 +1,5 @@ | ||
### 0.4.0 / 2014-11-08 | ||
* Support connection via HTTP proxies using `CONNECT` | ||
### 0.3.6 / 2014-10-04 | ||
@@ -2,0 +6,0 @@ |
@@ -12,3 +12,3 @@ var Emitter = require('events').EventEmitter, | ||
this._maxLength = this._options.maxLength || this.MAX_LENGTH; | ||
this.__headers = new Headers(); | ||
this._headers = new Headers(); | ||
this.__queue = []; | ||
@@ -61,3 +61,3 @@ this.readyState = 0; | ||
if (this.readyState > 0) return false; | ||
this.__headers.set(name, value); | ||
this._headers.set(name, value); | ||
return true; | ||
@@ -64,0 +64,0 @@ }, |
var url = require('url'), | ||
util = require('util'), | ||
HttpParser = require('./http_parser'), | ||
HttpParser = require('../http_parser'), | ||
Base = require('./base'), | ||
Hybi = require('./hybi'); | ||
Hybi = require('./hybi'), | ||
Proxy = require('./proxy'); | ||
var Client = function(url, options) { | ||
var Client = function(_url, options) { | ||
this.version = 'hybi-13'; | ||
Hybi.call(this, null, url, options); | ||
Hybi.call(this, null, _url, options); | ||
@@ -15,2 +16,19 @@ this.readyState = -1; | ||
this._http = new HttpParser('response'); | ||
var uri = url.parse(this.url), | ||
auth = uri.auth && new Buffer(uri.auth, 'utf8').toString('base64'); | ||
this._pathname = (uri.pathname || '/') + (uri.search || ''); | ||
this._headers.set('Host', uri.host); | ||
this._headers.set('Upgrade', 'websocket'); | ||
this._headers.set('Connection', 'Upgrade'); | ||
this._headers.set('Sec-WebSocket-Key', this._key); | ||
this._headers.set('Sec-WebSocket-Version', '13'); | ||
if (this._protocols.length > 0) | ||
this._headers.set('Sec-WebSocket-Protocol', this._protocols.join(', ')); | ||
if (auth) | ||
this._headers.set('Authorization', 'Basic ' + auth); | ||
}; | ||
@@ -26,2 +44,6 @@ util.inherits(Client, Hybi); | ||
var instance = { | ||
proxy: function(origin, options) { | ||
return new Proxy(this, origin, options); | ||
}, | ||
start: function() { | ||
@@ -39,3 +61,3 @@ if (this.readyState !== -1) return false; | ||
if (!this._http.isComplete()) return; | ||
this._validateHandshake(); | ||
@@ -46,19 +68,6 @@ this.parse(this._http.body); | ||
_handshakeRequest: function() { | ||
var uri = url.parse(this.url); | ||
var start = 'GET ' + this._pathname + ' HTTP/1.1', | ||
headers = [start, this._headers.toString(), '']; | ||
var headers = [ 'GET ' + (uri.pathname || '/') + (uri.search || '') + ' HTTP/1.1', | ||
'Host: ' + uri.hostname + (uri.port ? ':' + uri.port : ''), | ||
'Upgrade: websocket', | ||
'Connection: Upgrade', | ||
'Sec-WebSocket-Key: ' + this._key, | ||
'Sec-WebSocket-Version: 13' | ||
]; | ||
if (this._protocols.length > 0) | ||
headers.push('Sec-WebSocket-Protocol: ' + this._protocols.join(', ')); | ||
if (uri.auth) | ||
headers.push('Authorization: Basic ' + new Buffer(uri.auth, 'utf8').toString('base64')); | ||
return new Buffer(headers.concat(this.__headers.toString(), '').join('\r\n'), 'utf8'); | ||
return new Buffer(headers.join('\r\n'), 'utf8'); | ||
}, | ||
@@ -65,0 +74,0 @@ |
@@ -8,2 +8,7 @@ var Base = require('./base'), | ||
this.version = 'hixie-75'; | ||
this._headers.set('Upgrade', 'WebSocket'); | ||
this._headers.set('Connection', 'Upgrade'); | ||
this._headers.set('WebSocket-Origin', this._request.headers.origin); | ||
this._headers.set('WebSocket-Location', this.url); | ||
}; | ||
@@ -92,10 +97,6 @@ util.inherits(Draft75, Base); | ||
_handshakeResponse: function() { | ||
return new Buffer('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' + | ||
'Upgrade: WebSocket\r\n' + | ||
'Connection: Upgrade\r\n' + | ||
'WebSocket-Origin: ' + this._request.headers.origin + '\r\n' + | ||
'WebSocket-Location: ' + this.url + '\r\n' + | ||
this.__headers.toString() + | ||
'\r\n', | ||
'utf8'); | ||
var start = 'HTTP/1.1 101 Web Socket Protocol Handshake', | ||
headers = [start, this._headers.toString(), '']; | ||
return new Buffer(headers.join('\r\n'), 'utf8'); | ||
}, | ||
@@ -102,0 +103,0 @@ |
@@ -29,2 +29,9 @@ var Base = require('./base'), | ||
this.version = 'hixie-76'; | ||
this._headers.clear(); | ||
this._headers.set('Upgrade', 'WebSocket'); | ||
this._headers.set('Connection', 'Upgrade'); | ||
this._headers.set('Sec-WebSocket-Origin', this._request.headers.origin); | ||
this._headers.set('Sec-WebSocket-Location', this.url); | ||
}; | ||
@@ -52,10 +59,6 @@ util.inherits(Draft76, Draft75); | ||
_handshakeResponse: function() { | ||
return new Buffer('HTTP/1.1 101 WebSocket Protocol Handshake\r\n' + | ||
'Upgrade: WebSocket\r\n' + | ||
'Connection: Upgrade\r\n' + | ||
'Sec-WebSocket-Origin: ' + this._request.headers.origin + '\r\n' + | ||
'Sec-WebSocket-Location: ' + this.url + '\r\n' + | ||
this.__headers.toString() + | ||
'\r\n', | ||
'binary'); | ||
var start = 'HTTP/1.1 101 WebSocket Protocol Handshake', | ||
headers = [start, this._headers.toString(), '']; | ||
return new Buffer(headers.join('\r\n'), 'binary'); | ||
}, | ||
@@ -62,0 +65,0 @@ |
var Headers = function() { | ||
this.clear(); | ||
}; | ||
Headers.prototype.ALLOWED_DUPLICATES = ['set-cookie', 'set-cookie2', 'warning', 'www-authenticate']; | ||
Headers.prototype.clear = function() { | ||
this._sent = {}; | ||
@@ -6,4 +12,2 @@ this._lines = []; | ||
Headers.prototype.ALLOWED_DUPLICATES = ['set-cookie', 'set-cookie2', 'warning', 'www-authenticate'] | ||
Headers.prototype.set = function(name, value) { | ||
@@ -16,3 +20,3 @@ if (value === undefined) return; | ||
var key = name.toLowerCase(); | ||
if (!this._sent.hasOwnProperty(key) || this.ALLOWED_DUPLICATES.indexOf(key) < 0) { | ||
if (!this._sent.hasOwnProperty(key) || this.ALLOWED_DUPLICATES.indexOf(key) >= 0) { | ||
this._sent[key] = true; | ||
@@ -19,0 +23,0 @@ this._lines.push(name + ': ' + value + '\r\n'); |
@@ -22,11 +22,17 @@ var crypto = require('crypto'), | ||
var protos = this._request.headers['sec-websocket-protocol'], | ||
var secKey = this._request.headers['sec-websocket-key'], | ||
protos = this._request.headers['sec-websocket-protocol'], | ||
version = this._request.headers['sec-websocket-version'], | ||
supported = this._protocols; | ||
this._headers.set('Upgrade', 'websocket'); | ||
this._headers.set('Connection', 'Upgrade'); | ||
this._headers.set('Sec-WebSocket-Accept', Hybi.generateAccept(secKey)); | ||
if (protos !== undefined) { | ||
if (typeof protos === 'string') protos = protos.split(/\s*,\s*/); | ||
this.protocol = protos.filter(function(p) { return supported.indexOf(p) >= 0 })[0]; | ||
if (this.protocol) this._headers.set('Sec-WebSocket-Protocol', this.protocol); | ||
} | ||
var version = this._request.headers['sec-websocket-version']; | ||
this.version = 'hybi-' + version; | ||
@@ -227,16 +233,6 @@ }; | ||
_handshakeResponse: function() { | ||
var secKey = this._request.headers['sec-websocket-key']; | ||
if (!secKey) return ''; | ||
var start = 'HTTP/1.1 101 Switching Protocols', | ||
headers = [start, this._headers.toString(), '']; | ||
var headers = [ | ||
'HTTP/1.1 101 Switching Protocols', | ||
'Upgrade: websocket', | ||
'Connection: Upgrade', | ||
'Sec-WebSocket-Accept: ' + Hybi.generateAccept(secKey) | ||
]; | ||
if (this.protocol) | ||
headers.push('Sec-WebSocket-Protocol: ' + this.protocol); | ||
return new Buffer(headers.concat(this.__headers.toString(), '').join('\r\n'), 'utf8'); | ||
return new Buffer(headers.join('\r\n'), 'utf8'); | ||
}, | ||
@@ -243,0 +239,0 @@ |
var util = require('util'), | ||
HttpParser = require('./http_parser'), | ||
HttpParser = require('../http_parser'), | ||
Base = require('./base'), | ||
@@ -4,0 +4,0 @@ Draft75 = require('./draft75'), |
@@ -8,3 +8,3 @@ { "name" : "websocket-driver" | ||
, "version" : "0.3.6" | ||
, "version" : "0.4.0" | ||
, "engines" : {"node": ">=0.4.0"} | ||
@@ -11,0 +11,0 @@ , "main" : "./lib/websocket/driver" |
@@ -137,13 +137,13 @@ # websocket-driver [![Build Status](https://travis-ci.org/faye/websocket-driver-node.svg)](https://travis-ci.org/faye/websocket-driver-node) | ||
var driver = websocket.client('ws://www.example.com/socket'), | ||
tcp = net.createConnection(80, 'www.example.com'); | ||
tcp = net.connect(80, 'www.example.com'); | ||
tcp.pipe(driver.io).pipe(tcp); | ||
tcp.on('connect', function() { | ||
driver.start(); | ||
}); | ||
driver.messages.on('data', function(message) { | ||
console.log('Got a message', message); | ||
}); | ||
tcp.on('connect', function() { | ||
driver.start(); | ||
}); | ||
``` | ||
@@ -158,2 +158,61 @@ | ||
### HTTP Proxies | ||
The client driver supports connections via HTTP proxies using the `CONNECT` | ||
method. Instead of sending the WebSocket handshake immediately, it will send a | ||
`CONNECT` request, wait for a `200` response, and then proceed as normal. | ||
To use this feature, call `driver.proxy(url)` where `url` is the origin of the | ||
proxy, including a username and password if required. This produces a duplex | ||
stream that you should pipe in and out of your TCP connection to the proxy | ||
server. When the proxy emits `connect`, you can then pipe `driver.io` to your | ||
TCP stream and call `driver.start()`. | ||
```js | ||
var net = require('net'), | ||
websocket = require('websocket-driver'); | ||
var driver = websocket.client('ws://www.example.com/socket'), | ||
proxy = driver.proxy('http://username:password@proxy.example.com'), | ||
tcp = net.connect(80, 'proxy.example.com'); | ||
tcp.pipe(proxy).pipe(tcp, {end: false}); | ||
tcp.on('connect', function() { | ||
proxy.start(); | ||
}); | ||
proxy.on('connect', function() { | ||
driver.io.pipe(tcp).pipe(driver.io); | ||
driver.start(); | ||
}); | ||
driver.messages.on('data', function(message) { | ||
console.log('Got a message', message); | ||
}); | ||
``` | ||
The proxy's `connect` event is also where you should perform a TLS handshake on | ||
your TCP stream, if you are connecting to a `wss:` endpoint. | ||
In the event that proxy connection fails, `proxy` will emit an `error`. You can | ||
inspect the proxy's response via `proxy.statusCode` and `proxy.headers`. | ||
```js | ||
proxy.on('error', function(error) { | ||
console.error(error.message); | ||
console.log(proxy.statusCode); | ||
console.log(proxy.headers); | ||
}); | ||
``` | ||
Before calling `proxy.start()` you can set custom headers using | ||
`proxy.setHeader()`: | ||
```js | ||
proxy.setHeader('User-Agent', 'node'); | ||
proxy.start(); | ||
``` | ||
### Driver API | ||
@@ -160,0 +219,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
56256
16
1162
366