Compare commits

...

22 Commits

Author SHA1 Message Date
James Coglan 052120b3d5 Bump version to 0.7.1. 2013-12-03 00:49:02 +00:00
James Coglan f97fd88e02 A little formatting change around network error handling. 2013-12-02 21:44:24 +00:00
faye a8481f8cdd Merge pull request #27 from ramsperger/master
Forward networking error events to the websocket event listeners.
2013-12-02 13:31:02 -08:00
James Coglan d0c9689747 Remove unneeded options existence check. 2013-12-02 21:19:20 +00:00
James Coglan e668e64271 Expose the driver's maxLength option. 2013-12-02 21:15:32 +00:00
James Coglan f0b97a8005 Restructure tests slightly. 2013-12-02 13:08:02 +00:00
ramsperger e3cc891187 Forward networking error events to the websocket event listeners.
Handshake failures from HTTP were being fired as errors connection errors failed to show up. Dispatch network failure events (like connection refused, etc.)
2013-10-24 14:53:16 -04:00
James Coglan d1f2c2172d Bump version to 0.7.0. 2013-09-09 22:22:28 +01:00
James Coglan 0eb7d7173d Document the headers option to EventSource. 2013-08-24 11:52:47 +01:00
James Coglan 426e72786b Remove extra line break in EventSource headers. 2013-08-24 11:28:11 +01:00
James Coglan b126e31b81 Allow custom headers to be set on EventSource connections. 2013-08-24 11:21:05 +01:00
James Coglan 067df9aaf4 Bump version to 0.6.1. 2013-07-05 15:18:10 +01:00
James Coglan c6b40aefbb Older Nodes don't support chained pipe(). 2013-07-05 11:15:36 +01:00
James Coglan a68ff2c035 Start the driver asynchronously on the server to allow onopen hooks to be registered. 2013-07-04 21:55:30 +01:00
James Coglan da424b7d71 Modernize package.json. 2013-07-01 02:21:41 +01:00
James Coglan f2c08de98f Migrate to jstest. 2013-07-01 02:20:52 +01:00
James Coglan bbdbf1cb46 Correct package.json formatting. 2013-06-23 01:13:50 +01:00
James Coglan d5d4d9e009 Merge pull request #22 from cezor/master
Use singular repository to avoid warning
2013-06-22 17:12:14 -07:00
James Coglan 8a8e44b283 Support the 'ca' option to client connections, and remove the verify: false option. 2013-06-19 08:09:19 +01:00
Nick Nissen db9bbba6bc renamed repossitories keyword 2013-06-16 22:13:53 +02:00
Nick Nissen 085d8d2b43 Use singular repository to avoid warning 2013-06-15 13:54:20 +02:00
James Coglan ad572ca5e0 Turn the reflexive piping into a one-liner. 2013-05-29 02:21:53 +01:00
10 changed files with 121 additions and 77 deletions
+17
View File
@@ -1,3 +1,20 @@
### 0.7.1 / 2013-12-03
* Support the `maxLength` websocket-driver option
* Make the client emit `error` events on network errors
### 0.7.0 / 2013-09-09
* Allow the server to send custom headers with EventSource responses
### 0.6.1 / 2013-07-05
* Add `ca` option to the client for specifying certificate authorities
* Start the server driver asynchronously so that `onopen` handlers can be added
### 0.6.0 / 2013-05-12
* Add support for custom headers
+11 -3
View File
@@ -155,6 +155,8 @@ var ws = new WebSocket.Client(url, protocols, options);
* `headers` - an object containing key-value pairs representing HTTP headers to
be sent during the handshake process
* `maxLength` - the maximum allowed size of incoming message frames, in bytes.
The default value is `2^30 - 1`, or 1 byte short of 1 GiB.
* `ping` - an integer that sets how often the WebSocket should send ping
frames, measured in seconds
@@ -243,17 +245,23 @@ The `EventSource` object exposes the following properties:
When you initialize an EventSource with ` new EventSource()`, you can pass
configuration options after the `response` parameter. Available options are:
* <b>`headers`</b> is an object containing custom headers to be set on the
EventSource response.
* <b>`retry`</b> is a number that tells the client how long (in seconds) it
should wait after a dropped connection before attempting to reconnect.
* <b>`ping`</b> is a number that tells the server how often (in seconds) to
send 'ping' packets to the client to keep the connection open, to defeat
timeouts set by proxies. The client will ignore these messages.
For example, this creates a connection that pings every 15 seconds and is
retryable every 10 seconds if the connection is broken:
For example, this creates a connection that allows access from any origin, pings
every 15 seconds and is retryable every 10 seconds if the connection is broken:
```js
var es = new EventSource(request, response, {ping: 15, retry: 10});
var es = new EventSource(request, response, {
headers: {'Access-Control-Allow-Origin': '*'},
ping: 15,
retry: 10
});
```
You can send a ping message at any time by calling `es.ping()`. Unlike
+9 -2
View File
@@ -1,6 +1,7 @@
var Stream = require('stream').Stream,
util = require('util'),
driver = require('websocket-driver'),
Headers = require('websocket-driver/lib/websocket/driver/headers'),
API = require('./websocket/api'),
EventTarget = require('./websocket/api/event_target'),
Event = require('./websocket/api/event');
@@ -18,7 +19,12 @@ var EventSource = function(request, response, options) {
this.lastEventId = request.headers['last-event-id'] || '';
this.readyState = API.CONNECTING;
var self = this;
var headers = new Headers(),
self = this;
if (options.headers) {
for (var key in options.headers) headers.set(key, options.headers[key]);
}
if (!this._stream || !this._stream.writable) return;
process.nextTick(function() { self._open() });
@@ -30,7 +36,8 @@ var EventSource = function(request, response, options) {
'Content-Type: text/event-stream\r\n' +
'Cache-Control: no-cache, no-store\r\n' +
'Connection: close\r\n' +
'\r\n\r\n' +
headers.toString() +
'\r\n' +
'retry: ' + Math.floor(this._retry * 1000) + '\r\n\r\n';
this._write(handshake);
+7 -3
View File
@@ -9,8 +9,10 @@ var util = require('util'),
API = require('./websocket/api');
var WebSocket = function(request, socket, body, protocols, options) {
this._stream = socket;
this._driver = driver.http(request, {protocols: protocols});
options = options || {};
this._stream = socket;
this._driver = driver.http(request, {maxLength: options.maxLength, protocols: protocols});
var self = this;
if (!this._stream || !this._stream.writable) return;
@@ -28,7 +30,9 @@ var WebSocket = function(request, socket, body, protocols, options) {
this._stream.on(event, function() { self._finalize('', 1006) });
}, this);
this._driver.start();
process.nextTick(function() {
self._driver.start();
});
};
util.inherits(WebSocket, API);
+14 -6
View File
@@ -2,12 +2,15 @@ var util = require('util'),
net = require('net'),
tls = require('tls'),
driver = require('websocket-driver'),
API = require('./api');
API = require('./api'),
Event = require('./api/event');
var Client = function(url, protocols, options) {
options = options || {};
this.url = url;
this._uri = require('url').parse(url);
this._driver = driver.client(url, {protocols: protocols});
this._driver = driver.client(url, {maxLength: options.maxLength, protocols: protocols});
['open', 'error'].forEach(function(event) {
this._driver.on(event, function() {
@@ -21,7 +24,7 @@ var Client = function(url, protocols, options) {
tlsOptions = {},
self = this;
if (options && options.verify === false) tlsOptions.rejectUnauthorized = false;
if (options.ca) tlsOptions.ca = options.ca;
var connection = secure
? tls.connect(this._uri.port || 443, this._uri.hostname, tlsOptions, onConnect)
@@ -35,9 +38,14 @@ var Client = function(url, protocols, options) {
API.call(this, options);
['error', 'end'].forEach(function(event) {
this._stream.on(event, function() { self._finalize('', 1006) });
}, this);
this._stream.on('end', function() { self._finalize('', 1006) });
this._stream.on('error', function(error) {
var event = new Event('error', {message: 'Network error: ' + url + ': ' + error.message});
event.initEvent('error', false, false);
self.dispatchEvent(event);
self._finalize('', 1006);
});
};
util.inherits(Client, API);
+9 -14
View File
@@ -3,25 +3,20 @@
, "homepage" : "http://github.com/faye/faye-websocket-node"
, "author" : "James Coglan <jcoglan@gmail.com> (http://jcoglan.com/)"
, "keywords" : ["websocket", "eventsource"]
, "license" : "MIT"
, "version" : "0.6.0"
, "version" : "0.7.1"
, "engines" : {"node": ">=0.4.0"}
, "main" : "./lib/faye/websocket"
, "dependencies" : {"websocket-driver": ">=0.2.0"}
, "devDependencies" : {"jsclass": "", "pace": ""}
, "dependencies" : {"websocket-driver": ">=0.3.1"}
, "devDependencies" : {"jstest": "", "pace": ""}
, "scripts" : {"test": "node spec/runner.js"}
, "scripts" : {"test": "jstest spec/runner.js"}
, "repository" : { "type" : "git"
, "url" : "git://github.com/faye/faye-websocket-node.git"
}
, "bugs" : "http://github.com/faye/faye-websocket-node/issues"
, "licenses" : [ { "type" : "MIT"
, "url" : "http://www.opensource.org/licenses/mit-license.php"
}
]
, "repositories" : [ { "type" : "git"
, "url" : "git://github.com/faye/faye-websocket-node.git"
}
]
}
+25 -15
View File
@@ -1,16 +1,18 @@
var Client = require('../../../lib/faye/websocket/client')
var Client = require('../../../lib/faye/websocket/client'),
test = require('jstest').Test,
fs = require('fs')
JS.ENV.WebSocketSteps = JS.Test.asyncSteps({
var WebSocketSteps = test.asyncSteps({
server: function(port, secure, callback) {
this._adapter = new EchoServer()
this._adapter.listen(port, secure)
this._port = port
setTimeout(callback, 100)
process.nextTick(callback)
},
stop: function(callback) {
this._adapter.stop()
setTimeout(callback, 100)
process.nextTick(callback)
},
open_socket: function(url, protocols, callback) {
@@ -24,7 +26,9 @@ JS.ENV.WebSocketSteps = JS.Test.asyncSteps({
callback()
}
this._ws = new Client(url, protocols, {verify: false})
this._ws = new Client(url, protocols, {
ca: fs.readFileSync(__dirname + '/../../server.crt')
})
this._ws.onopen = function() { resume(true) }
this._ws.onclose = function() { resume(false) }
@@ -55,14 +59,20 @@ JS.ENV.WebSocketSteps = JS.Test.asyncSteps({
},
listen_for_message: function(callback) {
var self = this
var time = new Date().getTime(), self = this
this._ws.addEventListener('message', function(message) { self._message = message.data })
callback()
var timer = setInterval(function() {
if (self._message || new Date().getTime() - time > 3000) {
clearInterval(timer)
callback()
}
}, 100)
},
send_message: function(message, callback) {
this._ws.send(message)
setTimeout(callback, 100)
var ws = this._ws
setTimeout(function() { ws.send(message) }, 500)
process.nextTick(callback)
},
check_response: function(message, callback) {
@@ -77,7 +87,7 @@ JS.ENV.WebSocketSteps = JS.Test.asyncSteps({
})
JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
test.describe("Client", function() { with(this) {
include(WebSocketSteps)
before(function() {
@@ -106,26 +116,26 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
}})
it("can send and receive messages", function() { with(this) {
listen_for_message()
send_message("I expect this to be echoed")
listen_for_message()
check_response("I expect this to be echoed")
}})
it("sends numbers as strings", function() { with(this) {
listen_for_message()
send_message(13)
listen_for_message()
check_response("13")
}})
it("sends booleans as strings", function() { with(this) {
listen_for_message()
send_message(false)
listen_for_message()
check_response("false")
}})
it("sends arrays as strings", function() { with(this) {
listen_for_message()
send_message([13,14,15])
listen_for_message()
check_response("13,14,15")
}})
}})
@@ -137,8 +147,8 @@ JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) {
}})
it("cannot send and receive messages", function() { with(this) {
listen_for_message()
send_message("I expect this to be echoed")
listen_for_message()
check_no_response()
}})
}})
+4 -8
View File
@@ -1,12 +1,11 @@
require('jsclass')
var WebSocket = require('../lib/faye/websocket'),
fs = require('fs'),
http = require('http'),
https = require('https')
https = require('https'),
test = require('jstest').Test
JS.ENV.EchoServer = function() {}
EchoServer = function() {}
EchoServer.prototype.listen = function(port, ssl) {
var server = ssl
? https.createServer({
@@ -30,8 +29,5 @@ EchoServer.prototype.stop = function(callback, scope) {
}
JS.require('JS.Test', function() {
require('./faye/websocket/client_spec')
JS.Test.autorun()
})
require('./faye/websocket/client_spec')
+12 -13
View File
@@ -1,15 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICZTCCAc4CCQDxyrJZrFA0vjANBgkqhkiG9w0BAQUFADB3MQswCQYDVQQGEwJV
SzEPMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDTALBgNVBAoTBEZh
eWUxFTATBgNVBAMTDEphbWVzIENvZ2xhbjEgMB4GCSqGSIb3DQEJARYRamNvZ2xh
bkBnbWFpbC5jb20wHhcNMTEwODMwMTIzOTM2WhcNMTIwODI5MTIzOTM2WjB3MQsw
CQYDVQQGEwJVSzEPMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDTAL
BgNVBAoTBEZheWUxFTATBgNVBAMTDEphbWVzIENvZ2xhbjEgMB4GCSqGSIb3DQEJ
ARYRamNvZ2xhbkBnbWFpbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
AMDjU5fAK7fvUCZIYHcGXDZD/m9bY+B/UcwGcowk0hMQGYNlLKrpiK7xXBmZpDb6
r8n+7L/epBeSumbRIm4TDzeNHhuQGYLIeGQy7JNLoPBr6GxubjuJhKOOBnCqcupR
CLGG7Zw5oL4UvtZVH6kL9XnjyokQQbxxeoV9DqtqOaHHAgMBAAEwDQYJKoZIhvcN
AQEFBQADgYEAvQjSpzE1ahaeH1CmbLwckTxvWMZfxcZOrxTruK1po3cNnDOjGqFQ
KEkNj3K5WfwTBD4QgUdYDykhDX2m6HaMz4JEbgrwQv8M8FiswIA3dyGsbOifOk8H
r3GPNKMzm4o6vrn6RGOpt9q6bsWUBUHfNpP93uU2C9QEwDua3cFjDA0=
MIICKTCCAZICCQDtAJo/efrTvjANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJV
SzETMBEGA1UECBMKU29tZS1TdGF0ZTEPMA0GA1UEBxMGTG9uZG9uMRAwDgYDVQQK
EwdqY29nbGFuMRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMTMwNjE5MDcwNzQ1WhcN
MTQwNjE5MDcwNzQ1WjBZMQswCQYDVQQGEwJVSzETMBEGA1UECBMKU29tZS1TdGF0
ZTEPMA0GA1UEBxMGTG9uZG9uMRAwDgYDVQQKEwdqY29nbGFuMRIwEAYDVQQDEwls
b2NhbGhvc3QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALhPVRbctfcjCJEC
DsZfgtTMVYMsvV/miLxc7veumuuApe5y3DFuG8Tlz3/0wrvRm3dCSUOfIBK8ktor
VoY6QGHwrhYK2MhnJQOUTYC+FCyUp4zAYjRgJWd4uTii+uqRbLCPOF8jEx7VunTT
Lj9hu82IdRgT3OtqzPUoTmYXCXSZAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAcARo
TO7LTbII0HIsB7PePspFkwiuYQtvFqYm10I+4yuIdfPBdH0/OBhKvNC1O7tc7dmy
NPd8e5FXrt6qHDgCVh0kpg37sMJp42jUCn4lguWKN5dZPkzGrRFUfXvcx1qwdF2T
0CgyULvKWl9wt3Wp5feG8dNn1UZOGlZBZ+0GNyk=
-----END CERTIFICATE-----
+13 -13
View File
@@ -1,15 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDA41OXwCu371AmSGB3Blw2Q/5vW2Pgf1HMBnKMJNITEBmDZSyq
6Yiu8VwZmaQ2+q/J/uy/3qQXkrpm0SJuEw83jR4bkBmCyHhkMuyTS6Dwa+hsbm47
iYSjjgZwqnLqUQixhu2cOaC+FL7WVR+pC/V548qJEEG8cXqFfQ6rajmhxwIDAQAB
AoGABlk1DiCQD8y7mZb2PdSiwlJ4lFewsNnf6lQn/v7TPzdfb5ir4LAxBHkDLACH
jBuyH3bZefMs+W2l3u5xMKhF7uJqYcUlJdH2UwRfNG54Hn4SGAjQOK3ONer99sUf
USlsWSX1HjAAFMCBwUfKxMZA3VNQfYKTPdm0jSVf85kHO1ECQQD3s6ksm3QpfD0L
eG9EoDrqmwnEfpKoWPpz1O0i5tY9VcmhmLwS5Zpd7lB1qjTqzZk4RygU73T/BseJ
azehIHK5AkEAx1mSXt+ec8RfzVi/io6oqi2vOcACXRbOG4NQmqUWPnumdwsJjsjR
RzEoDFC2lu6448p9sgEq+CkbmgVeiyp4fwJAQnmgySve/NMuvslPcyddKGD7OhSN
30ghzrwx98/jZwqC1i9bKeccimDOjwVitjD/Ea9m/ldVGqwDGMoBX+iJYQJAEIOO
CYfyw1pQKV2huGOq+zX/nwQV7go2lrbhFX55gkGR/6iNaSOfmosq6yJAje5GqLAc
i4NnQNl+7NpnA5ZIFwJBAI1+OsZyjbRI99pYkTdOpa5IPlIb3j3JbSfjAWHLxlRY
0HLvN3Q1mE9kbB+uKH6syF/S7nALgsLgq7eHYvIaE/A=
MIICXAIBAAKBgQC4T1UW3LX3IwiRAg7GX4LUzFWDLL1f5oi8XO73rprrgKXuctwx
bhvE5c9/9MK70Zt3QklDnyASvJLaK1aGOkBh8K4WCtjIZyUDlE2AvhQslKeMwGI0
YCVneLk4ovrqkWywjzhfIxMe1bp00y4/YbvNiHUYE9zrasz1KE5mFwl0mQIDAQAB
AoGAfcTc6oHnxeHpKZJ+5I0uaOmafK2d+IAG1IqSIv/KBWQ/VoyYhz58woqTYtxx
udqZvPLFrdg6+a4mg6vJGkVLwp/PFi7r57/vqUR/P8SnuV0iTJZ7BczZHSffdzgT
9v2XUDFZ3ZSjIi+XkCMirHc7G8BVYImqjCGy80NX3YB5RRECQQDuX+udSSZi2I0C
gT/LnoVsb8JkanNALZH/U/XQog50I9aNf2GAAboUVsGuETL3I9f12Ku0A+xK5biv
s4P4g01FAkEAxfALp1Yzud+ooNmbbtSTE6hrUwjFeG1skEW4GvocB5ZiQqXwv59v
AmWedup7St2kamb5vNtcpewHGd2kUpatRQJARDwg7f0qh9EFTFpDML5H4yp6stPl
+dERoc0e6IH7MTOxDwAPoNzdr0TGXFWACU6xWyaSwAz/btEjdOgmNtUfIQJAFrWO
sLksIBQwBZxRv+p1oVi+T31/Imzzeq31DGtLkfdH+LuPHn0NQGomPyBx2soJFggQ
eQF15LdqrSYHt04APQJBAO2SPMC7MxDKdhryf6PDcaL/lTKSxRttQ72jZmDU9ujp
dcvFPgrQTa3iNLm4SWvARFXXZrrGEeDgKX7jVJygfI4=
-----END RSA PRIVATE KEY-----