faye 0.1.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of faye might be problematic. Click here for more details.
- data/History.txt +28 -0
- data/Jakefile +11 -0
- data/Manifest.txt +15 -17
- data/README.txt +149 -47
- data/build/faye-client-min.js +1 -0
- data/build/faye.js +868 -0
- data/examples/README.rdoc +41 -0
- data/examples/node/app.js +26 -0
- data/examples/node/faye-client-min.js +1 -0
- data/examples/node/faye.js +868 -0
- data/examples/rack/app.rb +6 -0
- data/examples/{soapbox → rack}/config.ru +1 -1
- data/examples/shared/public/favicon.ico +0 -0
- data/examples/{soapbox/views/index.erb → shared/public/index.html} +0 -0
- data/examples/{soapbox → shared}/public/jquery.js +0 -0
- data/examples/shared/public/robots.txt +0 -0
- data/examples/{soapbox → shared}/public/soapbox.js +0 -0
- data/examples/{soapbox → shared}/public/style.css +0 -0
- data/jake.yml +24 -9
- data/lib/faye-client-min.js +1 -0
- data/lib/faye.rb +2 -2
- data/lib/faye/rack_adapter.rb +44 -12
- data/lib/faye/server.rb +38 -31
- metadata +44 -23
- data/client/channel.js +0 -135
- data/client/client.js +0 -265
- data/client/faye.js +0 -95
- data/client/transport.js +0 -91
- data/client/util/class.js +0 -20
- data/client/util/event.js +0 -44
- data/client/util/json.js +0 -479
- data/client/util/uri.js +0 -69
- data/client/util/xhr.js +0 -99
- data/examples/soapbox/README +0 -22
- data/examples/soapbox/app.rb +0 -8
- data/lib/faye-min.js +0 -1
data/client/client.js
DELETED
@@ -1,265 +0,0 @@
|
|
1
|
-
Faye.Client = Faye.Class({
|
2
|
-
_UNCONNECTED: {},
|
3
|
-
_CONNECTING: {},
|
4
|
-
_CONNECTED: {},
|
5
|
-
_DISCONNECTED: {},
|
6
|
-
|
7
|
-
_HANDSHAKE: 'handshake',
|
8
|
-
_RETRY: 'retry',
|
9
|
-
_NONE: 'none',
|
10
|
-
|
11
|
-
DEFAULT_ENDPOINT: '<%= Faye::RackAdapter::DEFAULT_ENDPOINT %>',
|
12
|
-
MAX_DELAY: <%= Faye::Connection::MAX_DELAY %>,
|
13
|
-
INTERVAL: <%= Faye::Connection::INTERVAL * 1000 %>,
|
14
|
-
|
15
|
-
initialize: function(endpoint) {
|
16
|
-
this._endpoint = endpoint || this.DEFAULT_ENDPOINT;
|
17
|
-
this._transport = Faye.Transport.get(this);
|
18
|
-
this._state = this._UNCONNECTED;
|
19
|
-
this._outbox = [];
|
20
|
-
this._channels = new Faye.Channel.Tree();
|
21
|
-
|
22
|
-
this._advice = {reconnect: this._RETRY, interval: this.INTERVAL};
|
23
|
-
|
24
|
-
Faye.Event.on(Faye.ENV, 'beforeunload', this.disconnect, this);
|
25
|
-
},
|
26
|
-
|
27
|
-
// Request
|
28
|
-
// MUST include: * channel
|
29
|
-
// * version
|
30
|
-
// * supportedConnectionTypes
|
31
|
-
// MAY include: * minimumVersion
|
32
|
-
// * ext
|
33
|
-
// * id
|
34
|
-
//
|
35
|
-
// Success Response Failed Response
|
36
|
-
// MUST include: * channel MUST include: * channel
|
37
|
-
// * version * successful
|
38
|
-
// * supportedConnectionTypes * error
|
39
|
-
// * clientId MAY include: * supportedConnectionTypes
|
40
|
-
// * successful * advice
|
41
|
-
// MAY include: * minimumVersion * version
|
42
|
-
// * advice * minimumVersion
|
43
|
-
// * ext * ext
|
44
|
-
// * id * id
|
45
|
-
// * authSuccessful
|
46
|
-
handshake: function(callback, scope) {
|
47
|
-
if (this._advice.reconnect === this._NONE) return;
|
48
|
-
if (this._state !== this._UNCONNECTED) return;
|
49
|
-
|
50
|
-
this._state = this._CONNECTING;
|
51
|
-
var self = this, id = this.generateId();
|
52
|
-
|
53
|
-
this._transport.send({
|
54
|
-
channel: Faye.Channel.HANDSHAKE,
|
55
|
-
version: Faye.BAYEUX_VERSION,
|
56
|
-
supportedConnectionTypes: Faye.Transport.supportedConnectionTypes(),
|
57
|
-
id: id
|
58
|
-
|
59
|
-
}, function(response) {
|
60
|
-
if (response.id !== id) return;
|
61
|
-
|
62
|
-
if (!response.successful) {
|
63
|
-
setTimeout(function() { self.handshake(callback, scope) }, this._advice.interval);
|
64
|
-
return this._state = this._UNCONNECTED;
|
65
|
-
}
|
66
|
-
|
67
|
-
this._state = this._CONNECTED;
|
68
|
-
this._clientId = response.clientId;
|
69
|
-
this._transport = Faye.Transport.get(this, response.supportedConnectionTypes);
|
70
|
-
|
71
|
-
if (callback) callback.call(scope);
|
72
|
-
}, this);
|
73
|
-
},
|
74
|
-
|
75
|
-
// Request Response
|
76
|
-
// MUST include: * channel MUST include: * channel
|
77
|
-
// * clientId * successful
|
78
|
-
// * connectionType * clientId
|
79
|
-
// MAY include: * ext MAY include: * error
|
80
|
-
// * id * advice
|
81
|
-
// * ext
|
82
|
-
// * id
|
83
|
-
// * timestamp
|
84
|
-
connect: function(callback, scope) {
|
85
|
-
if (this._advice.reconnect === this._NONE) return;
|
86
|
-
|
87
|
-
if (this._advice.reconnect === this._HANDSHAKE || this._state === this._UNCONNECTED)
|
88
|
-
return this.handshake(function() { this.connect(callback, scope) }, this);
|
89
|
-
|
90
|
-
if (this._state !== this._CONNECTED) return;
|
91
|
-
|
92
|
-
if (this._connectionId) return;
|
93
|
-
this._connectionId = this.generateId();
|
94
|
-
var self = this;
|
95
|
-
|
96
|
-
this._transport.send({
|
97
|
-
channel: Faye.Channel.CONNECT,
|
98
|
-
clientId: this._clientId,
|
99
|
-
connectionType: this._transport.connectionType,
|
100
|
-
id: this._connectionId
|
101
|
-
|
102
|
-
}, function(response) {
|
103
|
-
if (response.id !== this._connectionId) return;
|
104
|
-
delete this._connectionId;
|
105
|
-
|
106
|
-
if (response.successful)
|
107
|
-
this.connect();
|
108
|
-
else
|
109
|
-
setTimeout(function() { self.connect() }, this._advice.interval);
|
110
|
-
}, this);
|
111
|
-
|
112
|
-
if (callback) callback.call(scope);
|
113
|
-
},
|
114
|
-
|
115
|
-
// Request Response
|
116
|
-
// MUST include: * channel MUST include: * channel
|
117
|
-
// * clientId * successful
|
118
|
-
// MAY include: * ext * clientId
|
119
|
-
// * id MAY include: * error
|
120
|
-
// * ext
|
121
|
-
// * id
|
122
|
-
disconnect: function() {
|
123
|
-
if (this._state !== this._CONNECTED) return;
|
124
|
-
this._state = this._DISCONNECTED;
|
125
|
-
|
126
|
-
this._transport.send({
|
127
|
-
channel: Faye.Channel.DISCONNECT,
|
128
|
-
clientId: this._clientId
|
129
|
-
});
|
130
|
-
|
131
|
-
this._channels = new Faye.Channel.Tree();
|
132
|
-
},
|
133
|
-
|
134
|
-
// Request Response
|
135
|
-
// MUST include: * channel MUST include: * channel
|
136
|
-
// * clientId * successful
|
137
|
-
// * subscription * clientId
|
138
|
-
// MAY include: * ext * subscription
|
139
|
-
// * id MAY include: * error
|
140
|
-
// * advice
|
141
|
-
// * ext
|
142
|
-
// * id
|
143
|
-
// * timestamp
|
144
|
-
subscribe: function(channels, callback, scope) {
|
145
|
-
if (this._state !== this._CONNECTED) return;
|
146
|
-
|
147
|
-
channels = [].concat(channels);
|
148
|
-
this._validateChannels(channels);
|
149
|
-
|
150
|
-
var id = this.generateId();
|
151
|
-
|
152
|
-
this._transport.send({
|
153
|
-
channel: Faye.Channel.SUBSCRIBE,
|
154
|
-
clientId: this._clientId,
|
155
|
-
subscription: channels,
|
156
|
-
id: id
|
157
|
-
|
158
|
-
}, function(response) {
|
159
|
-
if (response.id !== id) return;
|
160
|
-
if (!response.successful) return;
|
161
|
-
|
162
|
-
channels = [].concat(response.subscription);
|
163
|
-
Faye.each(channels, function(channel) {
|
164
|
-
this._channels.set(channel, [callback, scope]);
|
165
|
-
}, this);
|
166
|
-
}, this);
|
167
|
-
},
|
168
|
-
|
169
|
-
// Request Response
|
170
|
-
// MUST include: * channel MUST include: * channel
|
171
|
-
// * clientId * successful
|
172
|
-
// * subscription * clientId
|
173
|
-
// MAY include: * ext * subscription
|
174
|
-
// * id MAY include: * error
|
175
|
-
// * advice
|
176
|
-
// * ext
|
177
|
-
// * id
|
178
|
-
// * timestamp
|
179
|
-
unsubscribe: function(channels, callback, scope) {
|
180
|
-
if (this._state !== this._CONNECTED) return;
|
181
|
-
|
182
|
-
channels = [].concat(channels);
|
183
|
-
this._validateChannels(channels);
|
184
|
-
|
185
|
-
var id = this.generateId();
|
186
|
-
|
187
|
-
this._transport.send({
|
188
|
-
channel: Faye.Channel.UNSUBSCRIBE,
|
189
|
-
clientId: this._clientId,
|
190
|
-
subscription: channels,
|
191
|
-
id: id
|
192
|
-
|
193
|
-
}, function(response) {
|
194
|
-
if (response.id !== id) return;
|
195
|
-
if (!response.successful) return;
|
196
|
-
|
197
|
-
channels = [].concat(response.subscription);
|
198
|
-
Faye.each(channels, function(channel) {
|
199
|
-
this._channels.set(channel, null);
|
200
|
-
}, this);
|
201
|
-
}, this);
|
202
|
-
},
|
203
|
-
|
204
|
-
// Request Response
|
205
|
-
// MUST include: * channel MUST include: * channel
|
206
|
-
// * data * successful
|
207
|
-
// MAY include: * clientId MAY include: * id
|
208
|
-
// * id * error
|
209
|
-
// * ext * ext
|
210
|
-
publish: function(channel, data) {
|
211
|
-
if (this._state !== this._CONNECTED) return;
|
212
|
-
this._validateChannels([channel]);
|
213
|
-
|
214
|
-
this.enqueue({
|
215
|
-
channel: channel,
|
216
|
-
data: data,
|
217
|
-
clientId: this._clientId
|
218
|
-
});
|
219
|
-
|
220
|
-
if (this._timeout) return;
|
221
|
-
var self = this;
|
222
|
-
|
223
|
-
this._timeout = setTimeout(function() {
|
224
|
-
delete self._timeout;
|
225
|
-
self.flush();
|
226
|
-
}, this.MAX_DELAY * 1000);
|
227
|
-
},
|
228
|
-
|
229
|
-
generateId: function(bitdepth) {
|
230
|
-
bitdepth = bitdepth || 32;
|
231
|
-
return Math.floor(Math.pow(2,bitdepth) * Math.random()).toString(16);
|
232
|
-
},
|
233
|
-
|
234
|
-
enqueue: function(message) {
|
235
|
-
this._outbox.push(message);
|
236
|
-
},
|
237
|
-
|
238
|
-
flush: function() {
|
239
|
-
this._transport.send(this._outbox);
|
240
|
-
this._outbox = [];
|
241
|
-
},
|
242
|
-
|
243
|
-
_validateChannels: function(channels) {
|
244
|
-
Faye.each(channels, function(channel) {
|
245
|
-
if (!Faye.Channel.isValid(channel))
|
246
|
-
throw '"' + channel + '" is not a valid channel name';
|
247
|
-
if (!Faye.Channel.isSubscribable(channel))
|
248
|
-
throw 'Clients may not subscribe to channel "' + channel + '"';
|
249
|
-
});
|
250
|
-
},
|
251
|
-
|
252
|
-
_handleAdvice: function(advice) {
|
253
|
-
Faye.extend(this._advice, advice);
|
254
|
-
if (this._advice.reconnect === this._HANDSHAKE) this._clientId = null;
|
255
|
-
},
|
256
|
-
|
257
|
-
_sendToSubscribers: function(message) {
|
258
|
-
var channels = this._channels.glob(message.channel);
|
259
|
-
Faye.each(channels, function(callback) {
|
260
|
-
if (!callback) return;
|
261
|
-
callback[0].call(callback[1], message.data);
|
262
|
-
});
|
263
|
-
}
|
264
|
-
});
|
265
|
-
|
data/client/faye.js
DELETED
@@ -1,95 +0,0 @@
|
|
1
|
-
if (!this.Faye) Faye = {};
|
2
|
-
|
3
|
-
Faye.extend = function(dest, source, overwrite) {
|
4
|
-
if (!source) return dest;
|
5
|
-
for (var key in source) {
|
6
|
-
if (source.hasOwnProperty(key) && dest[key] !== source[key]) {
|
7
|
-
if (!dest.hasOwnProperty(key) || overwrite !== false)
|
8
|
-
dest[key] = source[key];
|
9
|
-
}
|
10
|
-
}
|
11
|
-
return dest;
|
12
|
-
};
|
13
|
-
|
14
|
-
Faye.extend(Faye, {
|
15
|
-
BAYEUX_VERSION: '<%= Faye::BAYEUX_VERSION %>',
|
16
|
-
ENV: this,
|
17
|
-
|
18
|
-
VERSION: '<%= Faye::VERSION %>',
|
19
|
-
|
20
|
-
Grammar: {
|
21
|
-
<% %w[ LOWALPHA UPALPHA ALPHA DIGIT
|
22
|
-
ALPHANUM MARK STRING TOKEN
|
23
|
-
INTEGER
|
24
|
-
|
25
|
-
CHANNEL_SEGMENT CHANNEL_SEGMENTS
|
26
|
-
CHANNEL_NAME
|
27
|
-
|
28
|
-
WILD_CARD CHANNEL_PATTERN
|
29
|
-
|
30
|
-
VERSION_ELEMENT VERSION
|
31
|
-
|
32
|
-
CLIENT_ID ID
|
33
|
-
|
34
|
-
ERROR_MESSAGE ERROR_ARGS
|
35
|
-
ERROR_CODE ERROR ].each do |bnf| %>
|
36
|
-
<%= bnf %>: /<%= Faye::Grammar.const_get(bnf).source %>/<%= bnf == 'ERROR' ? '' : ',' %>
|
37
|
-
<% end %>
|
38
|
-
},
|
39
|
-
|
40
|
-
commonElement: function(lista, listb) {
|
41
|
-
for (var i = 0, n = lista.length; i < n; i++) {
|
42
|
-
if (this.indexOf(listb, lista[i]) !== -1)
|
43
|
-
return lista[i];
|
44
|
-
}
|
45
|
-
return null;
|
46
|
-
},
|
47
|
-
|
48
|
-
indexOf: function(list, needle) {
|
49
|
-
for (var i = 0, n = list.length; i < n; i++) {
|
50
|
-
if (list[i] === needle) return i;
|
51
|
-
}
|
52
|
-
return -1;
|
53
|
-
},
|
54
|
-
|
55
|
-
each: function(object, callback, scope) {
|
56
|
-
if (object instanceof Array) {
|
57
|
-
for (var i = 0, n = object.length; i < n; i++) {
|
58
|
-
if (object[i] !== undefined)
|
59
|
-
callback.call(scope || null, object[i], i);
|
60
|
-
}
|
61
|
-
} else {
|
62
|
-
for (var key in object) {
|
63
|
-
if (object.hasOwnProperty(key))
|
64
|
-
callback.call(scope || null, key, object[key]);
|
65
|
-
}
|
66
|
-
}
|
67
|
-
},
|
68
|
-
|
69
|
-
size: function(object) {
|
70
|
-
var size = 0;
|
71
|
-
this.each(object, function() { size += 1 });
|
72
|
-
return size;
|
73
|
-
},
|
74
|
-
|
75
|
-
enumEqual: function(actual, expected) {
|
76
|
-
if (expected instanceof Array) {
|
77
|
-
if (!(actual instanceof Array)) return false;
|
78
|
-
var i = actual.length;
|
79
|
-
if (i !== expected.length) return false;
|
80
|
-
while (i--) {
|
81
|
-
if (actual[i] !== expected[i]) return false;
|
82
|
-
}
|
83
|
-
return true;
|
84
|
-
} else {
|
85
|
-
if (!(actual instanceof Object)) return false;
|
86
|
-
if (this.size(expected) !== this.size(actual)) return false;
|
87
|
-
var result = true;
|
88
|
-
this.each(actual, function(key, value) {
|
89
|
-
result = result && (expected[key] === value);
|
90
|
-
});
|
91
|
-
return result;
|
92
|
-
}
|
93
|
-
}
|
94
|
-
});
|
95
|
-
|
data/client/transport.js
DELETED
@@ -1,91 +0,0 @@
|
|
1
|
-
Faye.Transport = Faye.extend(Faye.Class({
|
2
|
-
initialize: function(client, endpoint) {
|
3
|
-
this._client = client;
|
4
|
-
this._endpoint = endpoint;
|
5
|
-
},
|
6
|
-
|
7
|
-
send: function(message, callback, scope) {
|
8
|
-
message = {message: JSON.stringify(message)};
|
9
|
-
return this.request(message, function(responses) {
|
10
|
-
if (!callback) return;
|
11
|
-
Faye.each([].concat(responses), function(response) {
|
12
|
-
|
13
|
-
callback.call(scope, response);
|
14
|
-
|
15
|
-
if (response.advice)
|
16
|
-
this._client._handleAdvice(response.advice);
|
17
|
-
|
18
|
-
if (response.data && response.channel)
|
19
|
-
this._client._sendToSubscribers(response);
|
20
|
-
|
21
|
-
}, this);
|
22
|
-
}, this);
|
23
|
-
}
|
24
|
-
}), {
|
25
|
-
get: function(client, connectionTypes) {
|
26
|
-
var endpoint = client._endpoint;
|
27
|
-
if (connectionTypes === undefined) connectionTypes = this.supportedConnectionTypes();
|
28
|
-
|
29
|
-
var types = Faye.URI.parse(endpoint).isLocal()
|
30
|
-
? ['long-polling', 'callback-polling']
|
31
|
-
: ['callback-polling'];
|
32
|
-
|
33
|
-
var type = Faye.commonElement(types, connectionTypes);
|
34
|
-
if (!type) throw 'Could not find a usable connection type for ' + endpoint;
|
35
|
-
|
36
|
-
var klass = this._connectionTypes[type];
|
37
|
-
return new klass(client, endpoint);
|
38
|
-
},
|
39
|
-
|
40
|
-
register: function(type, klass) {
|
41
|
-
this._connectionTypes[type] = klass;
|
42
|
-
klass.prototype.connectionType = type;
|
43
|
-
},
|
44
|
-
|
45
|
-
_connectionTypes: {},
|
46
|
-
|
47
|
-
supportedConnectionTypes: function() {
|
48
|
-
var list = [], key;
|
49
|
-
Faye.each(this._connectionTypes, function(key, type) { list.push(key) });
|
50
|
-
return list;
|
51
|
-
}
|
52
|
-
});
|
53
|
-
|
54
|
-
Faye.XHRTransport = Faye.Class(Faye.Transport, {
|
55
|
-
request: function(params, callback, scope) {
|
56
|
-
Faye.XHR.request('post', this._endpoint, params, function(response) {
|
57
|
-
if (callback) callback.call(scope, JSON.parse(response.text()));
|
58
|
-
});
|
59
|
-
}
|
60
|
-
});
|
61
|
-
Faye.Transport.register('long-polling', Faye.XHRTransport);
|
62
|
-
|
63
|
-
Faye.JSONPTransport = Faye.extend(Faye.Class(Faye.Transport, {
|
64
|
-
request: function(params, callback, scope) {
|
65
|
-
var head = document.getElementsByTagName('head')[0],
|
66
|
-
script = document.createElement('script'),
|
67
|
-
callbackName = Faye.JSONPTransport.getCallbackName(),
|
68
|
-
location = Faye.URI.parse(this._endpoint, params);
|
69
|
-
|
70
|
-
Faye.ENV[callbackName] = function(data) {
|
71
|
-
Faye.ENV[callbackName] = undefined;
|
72
|
-
try { delete Faye.ENV[callbackName] } catch (e) {}
|
73
|
-
head.removeChild(script);
|
74
|
-
if (callback) callback.call(scope, data);
|
75
|
-
};
|
76
|
-
|
77
|
-
location.params.jsonp = callbackName;
|
78
|
-
script.type = 'text/javascript';
|
79
|
-
script.src = location.toURL();
|
80
|
-
head.appendChild(script);
|
81
|
-
}
|
82
|
-
}), {
|
83
|
-
_cbCount: 0,
|
84
|
-
|
85
|
-
getCallbackName: function() {
|
86
|
-
this._cbCount += 1;
|
87
|
-
return '__jsonp' + this._cbCount + '__';
|
88
|
-
}
|
89
|
-
});
|
90
|
-
Faye.Transport.register('callback-polling', Faye.JSONPTransport);
|
91
|
-
|