faye 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of faye might be problematic. Click here for more details.
- data/History.txt +12 -0
- data/Manifest.txt +5 -0
- data/README.txt +25 -7
- data/Rakefile +1 -0
- data/build/faye-client-min.js +1 -1
- data/build/faye.js +367 -186
- data/examples/node/faye-client-min.js +1 -1
- data/examples/node/faye.js +367 -186
- data/examples/shared/public/index.html +1 -0
- data/examples/shared/public/mootools.js +4329 -0
- data/examples/shared/public/prototype.js +4874 -0
- data/jake.yml +3 -1
- data/lib/faye-client-min.js +1 -1
- data/lib/faye.rb +5 -2
- data/lib/faye/channel.rb +4 -0
- data/lib/faye/client.rb +53 -29
- data/lib/faye/connection.rb +16 -37
- data/lib/faye/rack_adapter.rb +33 -28
- data/lib/faye/server.rb +24 -23
- data/lib/faye/timeouts.rb +21 -0
- data/lib/faye/transport.rb +17 -4
- data/test/scenario.js +73 -37
- data/test/scenario.rb +104 -0
- data/test/test_channel.rb +7 -1
- data/test/test_clients.js +28 -10
- data/test/test_clients.rb +154 -0
- data/test/test_grammar.rb +1 -1
- data/test/test_server.rb +8 -7
- metadata +17 -11
data/History.txt
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
=== 0.3.2 / 2010-04-04
|
2
|
+
|
3
|
+
* Fix problems with JSON serialization when Prototype, MooTools present
|
4
|
+
* Make the client reconnect if it doesn't hear from the server after a timeout
|
5
|
+
* Stop JavaScript server returning NaN for advice.interval
|
6
|
+
* Make Ruby server return an integer for advice.interval
|
7
|
+
* Ensure EventMachine is running before handling messages
|
8
|
+
* Handle 'data' and 'end' events properly in Node HTTP API
|
9
|
+
* Switch to application/json for content types and stop using querystring format in POST bodies
|
10
|
+
* Respond to any URL path under the mount point, not just the exact match
|
11
|
+
|
12
|
+
|
1
13
|
=== 0.3.1 / 2010-03-09
|
2
14
|
|
3
15
|
* Pass client down through Rack stack as env['faye.client']
|
data/Manifest.txt
CHANGED
@@ -10,6 +10,8 @@ examples/README.rdoc
|
|
10
10
|
examples/shared/public/index.html
|
11
11
|
examples/shared/public/favicon.ico
|
12
12
|
examples/shared/public/jquery.js
|
13
|
+
examples/shared/public/mootools.js
|
14
|
+
examples/shared/public/prototype.js
|
13
15
|
examples/shared/public/robots.txt
|
14
16
|
examples/shared/public/soapbox.js
|
15
17
|
examples/shared/public/style.css
|
@@ -30,9 +32,12 @@ lib/faye/grammar.rb
|
|
30
32
|
lib/faye/namespace.rb
|
31
33
|
lib/faye/rack_adapter.rb
|
32
34
|
lib/faye/server.rb
|
35
|
+
lib/faye/timeouts.rb
|
33
36
|
lib/faye/transport.rb
|
34
37
|
test/scenario.js
|
38
|
+
test/scenario.rb
|
35
39
|
test/test_channel.rb
|
36
40
|
test/test_clients.js
|
41
|
+
test/test_clients.rb
|
37
42
|
test/test_grammar.rb
|
38
43
|
test/test_server.rb
|
data/README.txt
CHANGED
@@ -34,7 +34,7 @@ project of mine, but was not written to scale across multiple processes
|
|
34
34
|
as required for deployment under Passenger. It has since been ported to
|
35
35
|
Node.js which is better designed for handling highly concurrent traffic.
|
36
36
|
If you use the Ruby version, I recommend deploying it behind Thin, an
|
37
|
-
event-
|
37
|
+
event-driven Ruby web server.
|
38
38
|
|
39
39
|
The two backends are architecturally identical, using evented messaging
|
40
40
|
throughout and maintaining subscription data in memory. Neither is geared
|
@@ -64,9 +64,19 @@ You should set up the client as follows:
|
|
64
64
|
<script type="text/javascript" src="/faye.js"></script>
|
65
65
|
|
66
66
|
<script type="text/javascript">
|
67
|
-
fayeClient = new Faye.Client('/faye');
|
67
|
+
fayeClient = new Faye.Client('/faye', {timeout: 120});
|
68
68
|
</script>
|
69
69
|
|
70
|
+
The client (and the Node.js and Rack server-side clients) accepts the following
|
71
|
+
options in its constructor:
|
72
|
+
|
73
|
+
* +timeout+ - the maximum time (seconds) to wait for a connection response
|
74
|
+
from the server before attempting to reconnect. This should be greater than
|
75
|
+
the timeout set up on the server side, the idea being that if the server
|
76
|
+
doesn't send a connection response within this time then there has probably
|
77
|
+
been a network failure and we should reconnect. When the client reconnects,
|
78
|
+
any existing channel subscriptions are re-established automatically.
|
79
|
+
|
70
80
|
Take care only to have one instance of the client per page; since each one
|
71
81
|
opens a long-running request you will hit the two-requests-per-host limit
|
72
82
|
and block all other Ajax calls if you use more than one client.
|
@@ -146,6 +156,12 @@ Both backends support the following initialization options:
|
|
146
156
|
on your frontend webserver to make sure Faye sends a response before
|
147
157
|
the server kills the connection.
|
148
158
|
|
159
|
+
Regarding the +mount+ parameter: Faye will respond to any path under the
|
160
|
+
mount point, so <tt>/faye</tt>, <tt>/faye.js</tt> and <tt>/faye/some/subpath</tt>
|
161
|
+
will all be handled by Faye rather than your application. This is so that
|
162
|
+
Faye can interoperate with clients that use different URLs for different
|
163
|
+
message types.
|
164
|
+
|
149
165
|
Usage examples and a demo app are in the +examples+ directory.
|
150
166
|
|
151
167
|
|
@@ -180,10 +196,10 @@ over HTTP or connect directly to the <tt>NodeAdapter</tt>. Either way,
|
|
180
196
|
the API for the client is exactly as it is in the browser.
|
181
197
|
|
182
198
|
// Remote client
|
183
|
-
client = new
|
199
|
+
client = new faye.Client('http://example.com/faye', {timeout: 120});
|
184
200
|
|
185
201
|
// Local client
|
186
|
-
server = new
|
202
|
+
server = new faye.NodeAdapter(options);
|
187
203
|
client = server.getClient();
|
188
204
|
|
189
205
|
Note <tt>getClient()</tt> returns the same client object every time you
|
@@ -218,11 +234,11 @@ stack of Rack middlewares.
|
|
218
234
|
|
219
235
|
=== Rack client
|
220
236
|
|
221
|
-
Again mirroring the Node tools, Faye has a
|
237
|
+
Again mirroring the Node tools, Faye has a server-side Ruby client that
|
222
238
|
can be used under EventMachine. Setup is identical:
|
223
239
|
|
224
240
|
# Remote client
|
225
|
-
client = Faye::Client.new('http://example.com/faye')
|
241
|
+
client = Faye::Client.new('http://example.com/faye', :timeout => 120)
|
226
242
|
|
227
243
|
# Local client
|
228
244
|
server = Faye::RackAdapter.new(options)
|
@@ -257,7 +273,7 @@ the Rack environment, for example in a Sinatra application:
|
|
257
273
|
If you want to hack on Faye, you'll need Node.js, Ruby and the following
|
258
274
|
gems installed:
|
259
275
|
|
260
|
-
sudo gem install eventmachine em-http-request rack thin json jake
|
276
|
+
sudo gem install eventmachine em-http-request rack thin json jake hoe
|
261
277
|
|
262
278
|
DO NOT edit any JavaScript files outside the +javascript+ and +test+
|
263
279
|
directories. They are generated using Jake, which you should run after
|
@@ -276,6 +292,8 @@ changes where appropriate.
|
|
276
292
|
== To-do
|
277
293
|
|
278
294
|
* Investigate WebSockets as a possible message transport
|
295
|
+
* Support Bayeux extensions for authentication
|
296
|
+
* Let local server-side clients listen to <tt>/meta/*</tt> channels
|
279
297
|
* Provide support for user-defined <tt>/service/*</tt> channels
|
280
298
|
* Allow server to scale to multiple nodes
|
281
299
|
|
data/Rakefile
CHANGED
data/build/faye-client-min.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
if(!this.Faye)Faye={};Faye.extend=function(a,b,c){if(!b)return a;for(var d in b){if(!b.hasOwnProperty(d))continue;if(a.hasOwnProperty(d)&&c===false)continue;if(a[d]!==b[d])a[d]=b[d]}return a};Faye.extend(Faye,{VERSION:'0.3.1',BAYEUX_VERSION:'1.0',ID_LENGTH:128,JSONP_CALLBACK:'jsonpcallback',CONNECTION_TYPES:["long-polling","callback-polling"],ENV:this,random:function(a){a=a||this.ID_LENGTH;if(a>32){var b=Math.ceil(a/32),c='';while(b--)c+=this.random(32);return c}var d=Math.pow(2,a);return Math.floor(Math.random()*d).toString(16)},Grammar:{LOWALPHA:/^[a-z]$/,UPALPHA:/^[A-Z]$/,ALPHA:/^([a-z]|[A-Z])$/,DIGIT:/^[0-9]$/,ALPHANUM:/^(([a-z]|[A-Z])|[0-9])$/,MARK:/^(\-|\_|\!|\~|\(|\)|\$|\@)$/,STRING:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,TOKEN:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,INTEGER:/^([0-9])+$/,CHANNEL_SEGMENT:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,CHANNEL_SEGMENTS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,CHANNEL_NAME:/^\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,WILD_CARD:/^\*{1,2}$/,CHANNEL_PATTERN:/^(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*\/\*{1,2}$/,VERSION_ELEMENT:/^(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*$/,VERSION:/^([0-9])+(\.(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*)*$/,CLIENT_ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ERROR_MESSAGE:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,ERROR_ARGS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*$/,ERROR_CODE:/^[0-9][0-9][0-9]$/,ERROR:/^([0-9][0-9][0-9]:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*|[0-9][0-9][0-9]::(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)$/},commonElement:function(a,b){for(var c=0,d=a.length;c<d;c++){if(this.indexOf(b,a[c])!==-1)return a[c]}return null},indexOf:function(a,b){for(var c=0,d=a.length;c<d;c++){if(a[c]===b)return c}return-1},each:function(a,b,c){if(a instanceof Array){for(var d=0,f=a.length;d<f;d++){if(a[d]!==undefined)b.call(c||null,a[d],d)}}else{for(var g in a){if(a.hasOwnProperty(g))b.call(c||null,g,a[g])}}},filter:function(a,b,c){var d=[];this.each(a,function(){if(b.apply(c,arguments))d.push(arguments[0])});return d},size:function(a){var b=0;this.each(a,function(){b+=1});return b},enumEqual:function(c,d){if(d instanceof Array){if(!(c instanceof Array))return false;var f=c.length;if(f!==d.length)return false;while(f--){if(c[f]!==d[f])return false}return true}else{if(!(c instanceof Object))return false;if(this.size(d)!==this.size(c))return false;var g=true;this.each(c,function(a,b){g=g&&(d[a]===b)});return g}}});Faye.Class=function(a,b){if(typeof a!=='function'){b=a;a=Object}var c=function(){if(!this.initialize)return this;return this.initialize.apply(this,arguments)||this};var d=function(){};d.prototype=a.prototype;c.prototype=new d();Faye.extend(c.prototype,b);return c};Faye.Deferrable={callback:function(a,b){if(this._t==='succeeded')return a.apply(b,this._m);this._9=this._9||[];this._9.push([a,b])},setDeferredStatus:function(){var b=Array.prototype.slice.call(arguments),c=b.shift();this._t=c;this._m=b;if(c!=='succeeded')return;if(!this._9)return;Faye.each(this._9,function(a){a[0].apply(a[1],this._m)},this);this._9=[]}};Faye.Observable={on:function(a,b,c){this._0=this._0||{};var d=this._0[a]=this._0[a]||[];d.push([b,c])},stopObserving:function(a,b,c){if(!this._0||!this._0[a])return;if(!b){delete this._0[a];return}var d=this._0[a],f=d.length;while(f--){if(b&&d[f][0]!==b)continue;if(c&&d[f][1]!==c)continue;d.splice(f,1)}},fire:function(){var b=Array.prototype.slice.call(arguments),c=b.shift();if(!this._0||!this._0[c])return;Faye.each(this._0[c],function(a){a[0].apply(a[1],b.slice())})}};Faye.Channel=Faye.Class({initialize:function(a){this.__id=this.name=a},push:function(a){this.fire('message',a)}});Faye.extend(Faye.Channel.prototype,Faye.Observable);Faye.extend(Faye.Channel,{HANDSHAKE:'/meta/handshake',CONNECT:'/meta/connect',SUBSCRIBE:'/meta/subscribe',UNSUBSCRIBE:'/meta/unsubscribe',DISCONNECT:'/meta/disconnect',META:'meta',SERVICE:'service',isValid:function(a){return Faye.Grammar.CHANNEL_NAME.test(a)||Faye.Grammar.CHANNEL_PATTERN.test(a)},parse:function(a){if(!this.isValid(a))return null;return a.split('/').slice(1)},isMeta:function(a){var b=this.parse(a);return b?(b[0]===this.META):null},isService:function(a){var b=this.parse(a);return b?(b[0]===this.SERVICE):null},isSubscribable:function(a){if(!this.isValid(a))return null;return!this.isMeta(a)&&!this.isService(a)},Tree:Faye.Class({initialize:function(a){this._1=a;this._5={}},eachChild:function(c,d){Faye.each(this._5,function(a,b){c.call(d,a,b)})},each:function(c,d,f){this.eachChild(function(a,b){a=c.concat(a);b.each(a,d,f)});if(this._1!==undefined)d.call(f,c,this._1)},map:function(c,d){var f=[];this.each([],function(a,b){f.push(c.call(d,a,b))});return f},get:function(a){var b=this.traverse(a);return b?b._1:null},set:function(a,b){var c=this.traverse(a,true);if(c)c._1=b},traverse:function(a,b){if(typeof a==='string')a=Faye.Channel.parse(a);if(a===null)return null;if(a.length===0)return this;var c=this._5[a[0]];if(!c&&!b)return null;if(!c)c=this._5[a[0]]=new Faye.Channel.Tree();return c.traverse(a.slice(1),b)},findOrCreate:function(a){var b=this.get(a);if(b)return b;b=new Faye.Channel(a);this.set(a,b);return b},glob:function(f){if(typeof f==='string')f=Faye.Channel.parse(f);if(f===null)return[];if(f.length===0)return(this._1===undefined)?[]:[this._1];var g=[];if(Faye.enumEqual(f,['*'])){Faye.each(this._5,function(a,b){if(b._1!==undefined)g.push(b._1)});return g}if(Faye.enumEqual(f,['**'])){g=this.map(function(a,b){return b});if(this._1!==undefined)g.pop();return g}Faye.each(this._5,function(b,c){if(b!==f[0]&&b!=='*')return;var d=c.glob(f.slice(1));Faye.each(d,function(a){g.push(a)})});if(this._5['**'])g.push(this._5['**']._1);return g}})});Faye.Namespace=Faye.Class({initialize:function(){this._n={}},generate:function(){var a=Faye.random();while(this._n.hasOwnProperty(a))a=Faye.random();return this._n[a]=a}});Faye.Transport=Faye.extend(Faye.Class({initialize:function(a,b){this._f=a;this._6=b},send:function(c,d,f){if(!(c instanceof Array)&&!c.id)c.id=this._f._o.generate();this.request(c,function(b){if(!d)return;Faye.each([].concat(b),function(a){if(a.id===c.id)d.call(f,a);if(a.advice)this._f.handleAdvice(a.advice);if(a.data&&a.channel)this._f.sendToSubscribers(a)},this)},this)}}),{get:function(c,d){var f=c._6;if(d===undefined)d=this.supportedConnectionTypes();var g=null;Faye.each(this._g,function(a,b){if(Faye.indexOf(d,a)<0)return;if(g)return;if(b.isUsable(f))g=b});if(!g)throw'Could not find a usable connection type for '+f;return new g(c,f)},register:function(a,b){this._g[a]=b;b.prototype.connectionType=a},_g:{},supportedConnectionTypes:function(){var c=[],d;Faye.each(this._g,function(a,b){c.push(a)});return c}});Faye.Client=Faye.Class({UNCONNECTED:1,CONNECTING:2,CONNECTED:3,DISCONNECTED:4,HANDSHAKE:'handshake',RETRY:'retry',NONE:'none',DEFAULT_ENDPOINT:'/bayeux',MAX_DELAY:0.1,INTERVAL:1000.0,initialize:function(a){this._6=a||this.DEFAULT_ENDPOINT;this._4=Faye.Transport.get(this);this._2=this.UNCONNECTED;this._o=new Faye.Namespace();this._h=[];this._a=new Faye.Channel.Tree();this._p=[];this._7={reconnect:this.RETRY,interval:this.INTERVAL};if(!Faye.Event)return;Faye.Event.on(Faye.ENV,'beforeunload',this.disconnect,this)},handshake:function(b,c){if(this._7.reconnect===this.NONE)return;if(this._2!==this.UNCONNECTED)return;this._2=this.CONNECTING;var d=this;this._4.send({channel:Faye.Channel.HANDSHAKE,version:Faye.BAYEUX_VERSION,supportedConnectionTypes:Faye.Transport.supportedConnectionTypes()},function(a){if(!a.successful){setTimeout(function(){d.handshake(b,c)},this._7.interval);return this._2=this.UNCONNECTED}this._2=this.CONNECTED;this._8=a.clientId;this._4=Faye.Transport.get(this,a.supportedConnectionTypes);if(b)b.call(c)},this)},connect:function(b,c){if(this._7.reconnect===this.NONE)return;if(this._2===this.DISCONNECTED)return;if(this._7.reconnect===this.HANDSHAKE||this._2===this.UNCONNECTED)return this.handshake(function(){this.connect(b,c)},this);if(this._2===this.CONNECTING)return this.callback(b,c);if(this._2!==this.CONNECTED)return;this.setDeferredStatus('succeeded');this.setDeferredStatus('deferred');if(b)b.call(c);if(this._i)return;this._i=this._o.generate();var d=this;this._4.send({channel:Faye.Channel.CONNECT,clientId:this._8,connectionType:this._4.connectionType,id:this._i},function(a){delete this._i;setTimeout(function(){d.connect()},this._7.interval)},this)},disconnect:function(){if(this._2!==this.CONNECTED)return;this._2=this.DISCONNECTED;this._4.send({channel:Faye.Channel.DISCONNECT,clientId:this._8});this._a=new Faye.Channel.Tree()},subscribe:function(c,d,f){this.connect(function(){c=[].concat(c);this._j(c);this._4.send({channel:Faye.Channel.SUBSCRIBE,clientId:this._8,subscription:c},function(b){if(!b.successful)return;c=[].concat(b.subscription);Faye.each(c,function(a){this._a.set(a,[d,f])},this)},this)},this)},unsubscribe:function(c,d,f){this.connect(function(){c=[].concat(c);this._j(c);this._4.send({channel:Faye.Channel.UNSUBSCRIBE,clientId:this._8,subscription:c},function(b){if(!b.successful)return;c=[].concat(b.subscription);Faye.each(c,function(a){this._a.set(a,null)},this)},this)},this)},publish:function(b,c){this.connect(function(){this._j([b]);this._u({channel:b,data:c,clientId:this._8});if(this._q)return;var a=this;this._q=setTimeout(function(){delete a._q;a._v()},this.MAX_DELAY*1000)},this)},handleAdvice:function(a){Faye.extend(this._7,a);if(this._7.reconnect===this.HANDSHAKE)this._8=null},sendToSubscribers:function(b){var c=this._a.glob(b.channel);Faye.each(c,function(a){if(!a)return;a[0].call(a[1],b.data)})},_u:function(a){this._h.push(a)},_v:function(){this._4.send(this._h);this._h=[]},_j:function(b){Faye.each(b,function(a){if(!Faye.Channel.isValid(a))throw'"'+a+'" is not a valid channel name';if(!Faye.Channel.isSubscribable(a))throw'Clients may not subscribe to channel "'+a+'"';})}});Faye.extend(Faye.Client.prototype,Faye.Deferrable);Faye.Event={_b:[],on:function(a,b,c,d){var f=function(){c.call(d)};if(a.addEventListener)a.addEventListener(b,f,false);else a.attachEvent('on'+b,f);this._b.push({_c:a,_k:b,_w:c,_d:d,_r:f})},detach:function(a,b,c,d){var f=this._b.length,g;while(f--){g=this._b[f];if((a&&a!==g._c)||(b&&b!==g._k)||(c&&c!==g._w)||(d&&d!==g._d))continue;if(g._c.removeEventListener)g._c.removeEventListener(g._k,g._r,false);else g._c.detachEvent('on'+g._k,g._r);this._b.splice(f,1);g=null}}};Faye.Event.on(Faye.ENV,'unload',Faye.Event.detach,Faye.Event);Faye.URI=Faye.extend(Faye.Class({queryString:function(){var c=[],d;Faye.each(this.params,function(a,b){c.push(encodeURIComponent(a)+'='+encodeURIComponent(b))});return c.join('&')},isLocal:function(){var a=Faye.URI.parse(Faye.ENV.location.href);var b=(a.hostname!==this.hostname)||(a.port!==this.port)||(a.protocol!==this.protocol);return!b},toURL:function(){return this.protocol+this.hostname+':'+this.port+this.pathname+'?'+this.queryString()}}),{parse:function(d,f){if(typeof d!=='string')return d;var g=new this();var k=function(b,c){d=d.replace(c,function(a){if(a)g[b]=a;return''})};k('protocol',/^https?\:\/+/);k('hostname',/^[^\/\:]+/);k('port',/^:[0-9]+/);Faye.extend(g,{protocol:'http://',hostname:Faye.ENV.location.hostname,port:Faye.ENV.location.port},false);if(!g.port)g.port=(g.protocol==='https://')?'443':'80';g.port=g.port.replace(/\D/g,'');var i=d.split('?'),h=i.shift(),l=i.join('?'),n=l?l.split('&'):[],o=n.length,j={};while(o--){i=n[o].split('=');j[decodeURIComponent(i[0]||'')]=decodeURIComponent(i[1]||'')}Faye.extend(j,f);g.pathname=h;g.params=j;return g}});Faye.XHR={request:function(a,b,c,d,f){var g=new this.Request(a,b,c,d,f);g.send();return g},getXhrObject:function(){return Faye.ENV.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},Request:Faye.Class({initialize:function(a,b,c,d,f){this._e=a.toUpperCase();this._6=Faye.URI.parse(b,c);this._p=(typeof d==='function')?{success:d}:d;this._d=f||null;this._3=null},send:function(){if(this._l)return;var a=this._6.pathname,b=this._6.queryString();if(this._e==='GET')a+='?'+b;var c=this._e==='POST'?b:'';this._l=true;this._3=Faye.XHR.getXhrObject();this._3.open(this._e,a,true);if(this._e==='POST')this._3.setRequestHeader('Content-Type','application/x-www-form-urlencoded');var d=this,f=function(){if(d._3.readyState!==4)return;if(g){clearInterval(g);g=null}Faye.Event.detach(Faye.ENV,'beforeunload',d.abort,d);d._l=false;d._x();d=null};var g=setInterval(f,10);Faye.Event.on(Faye.ENV,'beforeunload',this.abort,this);this._3.send(c)},abort:function(){this._3.abort()},_x:function(){var a=this._p;if(!a)return;return this.success()?a.success&&a.success.call(this._d,this):a.failure&&a.failure.call(this._d,this)},waiting:function(){return!!this._l},complete:function(){return this._3&&!this.waiting()},success:function(){if(!this.complete())return false;var a=this._3.status;return(a>=200&&a<300)||a===304||a===1223},failure:function(){if(!this.complete())return false;return!this.success()},text:function(){if(!this.complete())return null;return this._3.responseText},status:function(){if(!this.complete())return null;return this._3.status}})};if(!this.JSON){JSON={}}(function(){function l(a){return a<10?'0'+a:a}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(a){return this.getUTCFullYear()+'-'+l(this.getUTCMonth()+1)+'-'+l(this.getUTCDate())+'T'+l(this.getUTCHours())+':'+l(this.getUTCMinutes())+':'+l(this.getUTCSeconds())+'Z'};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()}}var n=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,o=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,j,p,s={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},m;function r(c){o.lastIndex=0;return o.test(c)?'"'+c.replace(o,function(a){var b=s[a];return typeof b==='string'?b:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+c+'"'}function q(a,b){var c,d,f,g,k=j,i,h=b[a];if(h&&typeof h==='object'&&typeof h.toJSON==='function'){h=h.toJSON(a)}if(typeof m==='function'){h=m.call(b,a,h)}switch(typeof h){case'string':return r(h);case'number':return isFinite(h)?String(h):'null';case'boolean':case'null':return String(h);case'object':if(!h){return'null'}j+=p;i=[];if(Object.prototype.toString.apply(h)==='[object Array]'){g=h.length;for(c=0;c<g;c+=1){i[c]=q(c,h)||'null'}f=i.length===0?'[]':j?'[\n'+j+i.join(',\n'+j)+'\n'+k+']':'['+i.join(',')+']';j=k;return f}if(m&&typeof m==='object'){g=m.length;for(c=0;c<g;c+=1){d=m[c];if(typeof d==='string'){f=q(d,h);if(f){i.push(r(d)+(j?': ':':')+f)}}}}else{for(d in h){if(Object.hasOwnProperty.call(h,d)){f=q(d,h);if(f){i.push(r(d)+(j?': ':':')+f)}}}}f=i.length===0?'{}':j?'{\n'+j+i.join(',\n'+j)+'\n'+k+'}':'{'+i.join(',')+'}';j=k;return f}}if(typeof JSON.stringify!=='function'){JSON.stringify=function(a,b,c){var d;j='';p='';if(typeof c==='number'){for(d=0;d<c;d+=1){p+=' '}}else if(typeof c==='string'){p=c}m=b;if(b&&typeof b!=='function'&&(typeof b!=='object'||typeof b.length!=='number')){throw new Error('JSON.stringify');}return q('',{'':a})}}if(typeof JSON.parse!=='function'){JSON.parse=function(g,k){var i;function h(a,b){var c,d,f=a[b];if(f&&typeof f==='object'){for(c in f){if(Object.hasOwnProperty.call(f,c)){d=h(f,c);if(d!==undefined){f[c]=d}else{delete f[c]}}}}return k.call(a,b,f)}n.lastIndex=0;if(n.test(g)){g=g.replace(n,function(a){return'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(g.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){i=eval('('+g+')');return typeof k==='function'?h({'':i},''):i}throw new SyntaxError('JSON.parse');}}}());Faye.XHRTransport=Faye.Class(Faye.Transport,{request:function(b,c,d){var f={message:JSON.stringify(b)};Faye.XHR.request('post',this._6,f,function(a){if(c)c.call(d,JSON.parse(a.text()))})}});Faye.XHRTransport.isUsable=function(a){return Faye.URI.parse(a).isLocal()};Faye.Transport.register('long-polling',Faye.XHRTransport);Faye.JSONPTransport=Faye.extend(Faye.Class(Faye.Transport,{request:function(b,c,d){var f={message:JSON.stringify(b)},g=document.getElementsByTagName('head')[0],k=document.createElement('script'),i=Faye.JSONPTransport.getCallbackName(),h=Faye.URI.parse(this._6,f);Faye.ENV[i]=function(a){Faye.ENV[i]=undefined;try{delete Faye.ENV[i]}catch(e){}g.removeChild(k);if(c)c.call(d,a)};h.params.jsonp=i;k.type='text/javascript';k.src=h.toURL();g.appendChild(k)}}),{_s:0,getCallbackName:function(){this._s+=1;return'__jsonp'+this._s+'__'}});Faye.JSONPTransport.isUsable=function(a){return true};Faye.Transport.register('callback-polling',Faye.JSONPTransport);
|
1
|
+
if(!this.Faye)Faye={};Faye.extend=function(a,b,c){if(!b)return a;for(var d in b){if(!b.hasOwnProperty(d))continue;if(a.hasOwnProperty(d)&&c===false)continue;if(a[d]!==b[d])a[d]=b[d]}return a};Faye.extend(Faye,{VERSION:'0.3.2',BAYEUX_VERSION:'1.0',ID_LENGTH:128,JSONP_CALLBACK:'jsonpcallback',CONNECTION_TYPES:["long-polling","callback-polling"],ENV:this,random:function(a){a=a||this.ID_LENGTH;if(a>32){var b=Math.ceil(a/32),c='';while(b--)c+=this.random(32);return c}var d=Math.pow(2,a);return Math.floor(Math.random()*d).toString(16)},Grammar:{LOWALPHA:/^[a-z]$/,UPALPHA:/^[A-Z]$/,ALPHA:/^([a-z]|[A-Z])$/,DIGIT:/^[0-9]$/,ALPHANUM:/^(([a-z]|[A-Z])|[0-9])$/,MARK:/^(\-|\_|\!|\~|\(|\)|\$|\@)$/,STRING:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,TOKEN:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,INTEGER:/^([0-9])+$/,CHANNEL_SEGMENT:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+$/,CHANNEL_SEGMENTS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,CHANNEL_NAME:/^\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*$/,WILD_CARD:/^\*{1,2}$/,CHANNEL_PATTERN:/^(\/(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)))+)*\/\*{1,2}$/,VERSION_ELEMENT:/^(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*$/,VERSION:/^([0-9])+(\.(([a-z]|[A-Z])|[0-9])(((([a-z]|[A-Z])|[0-9])|\-|\_))*)*$/,CLIENT_ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ID:/^((([a-z]|[A-Z])|[0-9]))+$/,ERROR_MESSAGE:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*$/,ERROR_ARGS:/^(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*$/,ERROR_CODE:/^[0-9][0-9][0-9]$/,ERROR:/^([0-9][0-9][0-9]:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*(,(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)*:(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*|[0-9][0-9][0-9]::(((([a-z]|[A-Z])|[0-9])|(\-|\_|\!|\~|\(|\)|\$|\@)| |\/|\*|\.))*)$/},commonElement:function(a,b){for(var c=0,d=a.length;c<d;c++){if(this.indexOf(b,a[c])!==-1)return a[c]}return null},indexOf:function(a,b){for(var c=0,d=a.length;c<d;c++){if(a[c]===b)return c}return-1},each:function(a,b,c){if(a instanceof Array){for(var d=0,f=a.length;d<f;d++){if(a[d]!==undefined)b.call(c||null,a[d],d)}}else{for(var g in a){if(a.hasOwnProperty(g))b.call(c||null,g,a[g])}}},filter:function(a,b,c){var d=[];this.each(a,function(){if(b.apply(c,arguments))d.push(arguments[0])});return d},size:function(a){var b=0;this.each(a,function(){b+=1});return b},enumEqual:function(c,d){if(d instanceof Array){if(!(c instanceof Array))return false;var f=c.length;if(f!==d.length)return false;while(f--){if(c[f]!==d[f])return false}return true}else{if(!(c instanceof Object))return false;if(this.size(d)!==this.size(c))return false;var g=true;this.each(c,function(a,b){g=g&&(d[a]===b)});return g}},toJSON:function(a){if(this.stringify)return this.stringify(a,function(key,value){return(this[key]instanceof Array)?this[key]:value});return JSON.stringify(a)},timestamp:function(){var b=new Date(),c=b.getFullYear(),d=b.getMonth()+1,f=b.getDate(),g=b.getHours(),j=b.getMinutes(),i=b.getSeconds();var h=function(a){return a<10?'0'+a:String(a)};return h(c)+'-'+h(d)+'-'+h(f)+' '+h(g)+':'+h(j)+':'+h(i)}});Faye.Class=function(a,b){if(typeof a!=='function'){b=a;a=Object}var c=function(){if(!this.initialize)return this;return this.initialize.apply(this,arguments)||this};var d=function(){};d.prototype=a.prototype;c.prototype=new d();Faye.extend(c.prototype,b);return c};Faye.Deferrable={callback:function(a,b){if(this._w==='succeeded')return a.apply(b,this._o);this._a=this._a||[];this._a.push([a,b])},setDeferredStatus:function(){var b=Array.prototype.slice.call(arguments),c=b.shift();this._w=c;this._o=b;if(c!=='succeeded')return;if(!this._a)return;Faye.each(this._a,function(a){a[0].apply(a[1],this._o)},this);this._a=[]}};Faye.Observable={on:function(a,b,c){this._2=this._2||{};var d=this._2[a]=this._2[a]||[];d.push([b,c])},stopObserving:function(a,b,c){if(!this._2||!this._2[a])return;if(!b){delete this._2[a];return}var d=this._2[a],f=d.length;while(f--){if(b&&d[f][0]!==b)continue;if(c&&d[f][1]!==c)continue;d.splice(f,1)}},fire:function(){var b=Array.prototype.slice.call(arguments),c=b.shift();if(!this._2||!this._2[c])return;Faye.each(this._2[c],function(a){a[0].apply(a[1],b.slice())})}};Faye.Logging={LOG_LEVELS:{error:3,warn:2,info:1,debug:0},logLevel:'error',log:function(a,b){if(!Faye.logger)return;var c=Faye.Logging.LOG_LEVELS;if(c[Faye.Logging.logLevel]>c[b])return;var d='['+b.toUpperCase()+'] [Faye',f=null;for(var g in Faye){if(f)continue;if(typeof Faye[g]!=='function')continue;if(this instanceof Faye[g])f=g}if(f)d+='.'+f;d+='] ';Faye.logger(Faye.timestamp()+' '+d+a)},error:function(a){this.log(a,'error')},warn:function(a){this.log(a,'warn')},info:function(a){this.log(a,'info')},debug:function(a){this.log(a,'debug')}};Faye.Timeouts={addTimeout:function(a,b,c,d){this._6=this._6||{};if(this._6.hasOwnProperty(a))return;var f=this;this._6[a]=setTimeout(function(){delete f._6[a];c.call(d)},1000*b)},removeTimeout:function(a){this._6=this._6||{};var b=this._6[a];if(!b)return;clearTimeout(b);delete this._6[a]}};Faye.Channel=Faye.Class({initialize:function(a){this.__id=this.name=a},push:function(a){this.fire('message',a)}});Faye.extend(Faye.Channel.prototype,Faye.Observable);Faye.extend(Faye.Channel,{HANDSHAKE:'/meta/handshake',CONNECT:'/meta/connect',SUBSCRIBE:'/meta/subscribe',UNSUBSCRIBE:'/meta/unsubscribe',DISCONNECT:'/meta/disconnect',META:'meta',SERVICE:'service',isValid:function(a){return Faye.Grammar.CHANNEL_NAME.test(a)||Faye.Grammar.CHANNEL_PATTERN.test(a)},parse:function(a){if(!this.isValid(a))return null;return a.split('/').slice(1)},isMeta:function(a){var b=this.parse(a);return b?(b[0]===this.META):null},isService:function(a){var b=this.parse(a);return b?(b[0]===this.SERVICE):null},isSubscribable:function(a){if(!this.isValid(a))return null;return!this.isMeta(a)&&!this.isService(a)},Tree:Faye.Class({initialize:function(a){this._3=a;this._8={}},eachChild:function(c,d){Faye.each(this._8,function(a,b){c.call(d,a,b)})},each:function(c,d,f){this.eachChild(function(a,b){a=c.concat(a);b.each(a,d,f)});if(this._3!==undefined)d.call(f,c,this._3)},getKeys:function(){return this.map(function(a,b){return'/'+a.join('/')})},map:function(c,d){var f=[];this.each([],function(a,b){f.push(c.call(d,a,b))});return f},get:function(a){var b=this.traverse(a);return b?b._3:null},set:function(a,b){var c=this.traverse(a,true);if(c)c._3=b},traverse:function(a,b){if(typeof a==='string')a=Faye.Channel.parse(a);if(a===null)return null;if(a.length===0)return this;var c=this._8[a[0]];if(!c&&!b)return null;if(!c)c=this._8[a[0]]=new Faye.Channel.Tree();return c.traverse(a.slice(1),b)},findOrCreate:function(a){var b=this.get(a);if(b)return b;b=new Faye.Channel(a);this.set(a,b);return b},glob:function(f){if(typeof f==='string')f=Faye.Channel.parse(f);if(f===null)return[];if(f.length===0)return(this._3===undefined)?[]:[this._3];var g=[];if(Faye.enumEqual(f,['*'])){Faye.each(this._8,function(a,b){if(b._3!==undefined)g.push(b._3)});return g}if(Faye.enumEqual(f,['**'])){g=this.map(function(a,b){return b});if(this._3!==undefined)g.pop();return g}Faye.each(this._8,function(b,c){if(b!==f[0]&&b!=='*')return;var d=c.glob(f.slice(1));Faye.each(d,function(a){g.push(a)})});if(this._8['**'])g.push(this._8['**']._3);return g}})});Faye.Namespace=Faye.Class({initialize:function(){this._p={}},generate:function(){var a=Faye.random();while(this._p.hasOwnProperty(a))a=Faye.random();return this._p[a]=a}});Faye.Transport=Faye.extend(Faye.Class({initialize:function(a,b){this.debug('Created new transport for '+b);this._b=a;this._4=b},send:function(f,g,j){if(!(f instanceof Array)&&!f.id)f.id=this._b._q.generate();this.debug('Client '+this._b._0+' sending message to '+this._4+': '+Faye.toJSON(f));this.request(f,function(b){this.debug('Client '+this._b._0+' received from '+this._4+': '+Faye.toJSON(b));if(!g)return;var c=[],d=true;Faye.each([].concat(b),function(a){if(a.id===f.id){if(g.call(j,a)===false)d=false}if(a.advice)this._b.handleAdvice(a.advice);if(a.data&&a.channel)c.push(a)},this);if(d)this._b.deliverMessages(c)},this)}}),{get:function(c,d){var f=c._4;if(d===undefined)d=this.supportedConnectionTypes();var g=null;Faye.each(this._i,function(a,b){if(Faye.indexOf(d,a)<0)return;if(g)return;if(b.isUsable(f))g=b});if(!g)throw'Could not find a usable connection type for '+f;return new g(c,f)},register:function(a,b){this._i[a]=b;b.prototype.connectionType=a},_i:{},supportedConnectionTypes:function(){var c=[],d;Faye.each(this._i,function(a,b){c.push(a)});return c}});Faye.extend(Faye.Transport.prototype,Faye.Logging);Faye.Client=Faye.Class({UNCONNECTED:1,CONNECTING:2,CONNECTED:3,DISCONNECTED:4,HANDSHAKE:'handshake',RETRY:'retry',NONE:'none',CONNECTION_TIMEOUT:60.0,DEFAULT_ENDPOINT:'/bayeux',MAX_DELAY:0.1,INTERVAL:1000.0,initialize:function(a,b){this.info('New client created for '+a);this._4=a||this.DEFAULT_ENDPOINT;this._x=b||{};this._r=this._x.timeout||this.CONNECTION_TIMEOUT;this._7=Faye.Transport.get(this);this._1=this.UNCONNECTED;this._q=new Faye.Namespace();this._j=[];this._c=new Faye.Channel.Tree();this._s=[];this._9={reconnect:this.RETRY,interval:this.INTERVAL};if(!Faye.Event)return;Faye.Event.on(Faye.ENV,'beforeunload',this.disconnect,this)},handshake:function(b,c){if(this._9.reconnect===this.NONE)return;if(this._1!==this.UNCONNECTED)return;this._1=this.CONNECTING;var d=this;this.info('Initiating handshake with '+this._4);this._7.send({channel:Faye.Channel.HANDSHAKE,version:Faye.BAYEUX_VERSION,supportedConnectionTypes:Faye.Transport.supportedConnectionTypes()},function(a){if(!a.successful){this.info('Handshake unsuccessful');setTimeout(function(){d.handshake(b,c)},this._9.interval);return this._1=this.UNCONNECTED}this._1=this.CONNECTED;this._0=a.clientId;this._7=Faye.Transport.get(this,a.supportedConnectionTypes);this.info('Handshake successful: '+this._0);if(b)b.call(c)},this)},connect:function(b,c){if(this._9.reconnect===this.NONE)return;if(this._1===this.DISCONNECTED)return;if(this._9.reconnect===this.HANDSHAKE||this._1===this.UNCONNECTED){this._t();return this.handshake(function(){this.connect(b,c)},this)}if(this._1===this.CONNECTING)return this.callback(b,c);if(this._1!==this.CONNECTED)return;this.info('Calling deferred actions for '+this._0);this.setDeferredStatus('succeeded');this.setDeferredStatus('deferred');if(b)b.call(c);if(this._d)return;this._d=this._q.generate();var d=this;this.info('Initiating connection for '+this._0);this._7.send({channel:Faye.Channel.CONNECT,clientId:this._0,connectionType:this._7.connectionType,id:this._d},this._k(function(a){delete this._d;this.removeTimeout('reconnect');this.info('Closed connection for '+this._0);setTimeout(function(){d.connect()},this._9.interval)}));this._t()},disconnect:function(){if(this._1!==this.CONNECTED)return;this._1=this.DISCONNECTED;this.info('Disconnecting '+this._0);this._7.send({channel:Faye.Channel.DISCONNECT,clientId:this._0});this.info('Clearing channel listeners for '+this._0);this._c=new Faye.Channel.Tree()},subscribe:function(c,d,f){this.connect(function(){c=[].concat(c);this._l(c);this.info('Client '+this._0+' attempting to subscribe to ['+c.join(', ')+']');this._7.send({channel:Faye.Channel.SUBSCRIBE,clientId:this._0,subscription:c},this._k(function(b){if(!b.successful||!d)return;this.info('Subscription acknowledged for '+this._0+' to ['+c.join(', ')+']');c=[].concat(b.subscription);Faye.each(c,function(a){this._c.set(a,[d,f])},this)}))},this)},unsubscribe:function(c,d,f){this.connect(function(){c=[].concat(c);this._l(c);this.info('Client '+this._0+' attempting to unsubscribe from ['+c.join(', ')+']');this._7.send({channel:Faye.Channel.UNSUBSCRIBE,clientId:this._0,subscription:c},this._k(function(b){if(!b.successful)return;this.info('Unsubscription acknowledged for '+this._0+' from ['+c.join(', ')+']');c=[].concat(b.subscription);Faye.each(c,function(a){this._c.set(a,null)},this)}))},this)},publish:function(a,b){this.connect(function(){this._l([a]);this.info('Client '+this._0+' queueing published message to '+a+': '+Faye.toJSON(b));this._y({channel:a,data:b,clientId:this._0});this.addTimeout('publish',this.MAX_DELAY,this._z,this)},this)},handleAdvice:function(a){Faye.extend(this._9,a);if(this._9.reconnect===this.HANDSHAKE)this._0=null},deliverMessages:function(d){Faye.each(d,function(b){this.info('Client '+this._0+' calling listeners for '+b.channel+' with '+Faye.toJSON(b.data));var c=this._c.glob(b.channel);Faye.each(c,function(a){if(!a)return;a[0].call(a[1],b.data)})},this)},_t:function(){this.addTimeout('reconnect',this._r,function(){delete this._d;delete this._0;this._1=this.UNCONNECTED;this.info('Server took >'+this._r+'s to reply to connection for '+this._0+': attempting to reconnect');this.subscribe(this._c.getKeys())},this)},_y:function(a){this._j.push(a)},_z:function(){this._7.send(this._j);this._j=[]},_l:function(b){Faye.each(b,function(a){if(!Faye.Channel.isValid(a))throw'"'+a+'" is not a valid channel name';if(!Faye.Channel.isSubscribable(a))throw'Clients may not subscribe to channel "'+a+'"';})},_k:function(b){var c=this;return function(a){if(a.clientId!==c._0)return false;b.call(c,a);return true}}});Faye.extend(Faye.Client.prototype,Faye.Deferrable);Faye.extend(Faye.Client.prototype,Faye.Timeouts);Faye.extend(Faye.Client.prototype,Faye.Logging);Faye.Event={_e:[],on:function(a,b,c,d){var f=function(){c.call(d)};if(a.addEventListener)a.addEventListener(b,f,false);else a.attachEvent('on'+b,f);this._e.push({_f:a,_m:b,_A:c,_g:d,_u:f})},detach:function(a,b,c,d){var f=this._e.length,g;while(f--){g=this._e[f];if((a&&a!==g._f)||(b&&b!==g._m)||(c&&c!==g._A)||(d&&d!==g._g))continue;if(g._f.removeEventListener)g._f.removeEventListener(g._m,g._u,false);else g._f.detachEvent('on'+g._m,g._u);this._e.splice(f,1);g=null}}};Faye.Event.on(Faye.ENV,'unload',Faye.Event.detach,Faye.Event);Faye.URI=Faye.extend(Faye.Class({queryString:function(){var c=[],d;Faye.each(this.params,function(a,b){c.push(encodeURIComponent(a)+'='+encodeURIComponent(b))});return c.join('&')},isLocal:function(){var a=Faye.URI.parse(Faye.ENV.location.href);var b=(a.hostname!==this.hostname)||(a.port!==this.port)||(a.protocol!==this.protocol);return!b},toURL:function(){return this.protocol+this.hostname+':'+this.port+this.pathname+'?'+this.queryString()}}),{parse:function(d,f){if(typeof d!=='string')return d;var g=new this();var j=function(b,c){d=d.replace(c,function(a){if(a)g[b]=a;return''})};j('protocol',/^https?\:\/+/);j('hostname',/^[^\/\:]+/);j('port',/^:[0-9]+/);Faye.extend(g,{protocol:'http://',hostname:Faye.ENV.location.hostname,port:Faye.ENV.location.port},false);if(!g.port)g.port=(g.protocol==='https://')?'443':'80';g.port=g.port.replace(/\D/g,'');var i=d.split('?'),h=i.shift(),l=i.join('?'),n=l?l.split('&'):[],o=n.length,k={};while(o--){i=n[o].split('=');k[decodeURIComponent(i[0]||'')]=decodeURIComponent(i[1]||'')}if(typeof f==='object')Faye.extend(k,f);g.pathname=h;g.params=k;return g}});Faye.XHR={request:function(a,b,c,d,f){var g=new this.Request(a,b,c,d,f);g.send();return g},getXhrObject:function(){return Faye.ENV.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},Request:Faye.Class({initialize:function(a,b,c,d,f){this._h=a.toUpperCase();this._4=Faye.URI.parse(b,c);this._B=(typeof c==='string')?c:null;this._s=(typeof d==='function')?{success:d}:d;this._g=f||null;this._5=null},send:function(){if(this._n)return;var a=this._4.pathname,b=this._4.queryString();if(this._h==='GET')a+='?'+b;var c=(this._h==='POST')?(this._B||b):'';this._n=true;this._5=Faye.XHR.getXhrObject();this._5.open(this._h,a,true);if(this._h==='POST')this._5.setRequestHeader('Content-Type','application/json');var d=this,f=function(){if(d._5.readyState!==4)return;if(g){clearInterval(g);g=null}Faye.Event.detach(Faye.ENV,'beforeunload',d.abort,d);d._n=false;d._C();d=null};var g=setInterval(f,10);Faye.Event.on(Faye.ENV,'beforeunload',this.abort,this);this._5.send(c)},abort:function(){this._5.abort()},_C:function(){var a=this._s;if(!a)return;return this.success()?a.success&&a.success.call(this._g,this):a.failure&&a.failure.call(this._g,this)},waiting:function(){return!!this._n},complete:function(){return this._5&&!this.waiting()},success:function(){if(!this.complete())return false;var a=this._5.status;return(a>=200&&a<300)||a===304||a===1223},failure:function(){if(!this.complete())return false;return!this.success()},text:function(){if(!this.complete())return null;return this._5.responseText},status:function(){if(!this.complete())return null;return this._5.status}})};if(!this.JSON){JSON={}}(function(){function l(a){return a<10?'0'+a:a}if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(a){return this.getUTCFullYear()+'-'+l(this.getUTCMonth()+1)+'-'+l(this.getUTCDate())+'T'+l(this.getUTCHours())+':'+l(this.getUTCMinutes())+':'+l(this.getUTCSeconds())+'Z'};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()}}var n=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,o=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,k,p,s={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'},m;function r(c){o.lastIndex=0;return o.test(c)?'"'+c.replace(o,function(a){var b=s[a];return typeof b==='string'?b:'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+c+'"'}function q(a,b){var c,d,f,g,j=k,i,h=b[a];if(h&&typeof h==='object'&&typeof h.toJSON==='function'){h=h.toJSON(a)}if(typeof m==='function'){h=m.call(b,a,h)}switch(typeof h){case'string':return r(h);case'number':return isFinite(h)?String(h):'null';case'boolean':case'null':return String(h);case'object':if(!h){return'null'}k+=p;i=[];if(Object.prototype.toString.apply(h)==='[object Array]'){g=h.length;for(c=0;c<g;c+=1){i[c]=q(c,h)||'null'}f=i.length===0?'[]':k?'[\n'+k+i.join(',\n'+k)+'\n'+j+']':'['+i.join(',')+']';k=j;return f}if(m&&typeof m==='object'){g=m.length;for(c=0;c<g;c+=1){d=m[c];if(typeof d==='string'){f=q(d,h);if(f){i.push(r(d)+(k?': ':':')+f)}}}}else{for(d in h){if(Object.hasOwnProperty.call(h,d)){f=q(d,h);if(f){i.push(r(d)+(k?': ':':')+f)}}}}f=i.length===0?'{}':k?'{\n'+k+i.join(',\n'+k)+'\n'+j+'}':'{'+i.join(',')+'}';k=j;return f}}Faye.stringify=function(a,b,c){var d;k='';p='';if(typeof c==='number'){for(d=0;d<c;d+=1){p+=' '}}else if(typeof c==='string'){p=c}m=b;if(b&&typeof b!=='function'&&(typeof b!=='object'||typeof b.length!=='number')){throw new Error('JSON.stringify');}return q('',{'':a})};if(typeof JSON.stringify!=='function'){JSON.stringify=Faye.stringify}if(typeof JSON.parse!=='function'){JSON.parse=function(g,j){var i;function h(a,b){var c,d,f=a[b];if(f&&typeof f==='object'){for(c in f){if(Object.hasOwnProperty.call(f,c)){d=h(f,c);if(d!==undefined){f[c]=d}else{delete f[c]}}}}return j.call(a,b,f)}n.lastIndex=0;if(n.test(g)){g=g.replace(n,function(a){return'\\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(g.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){i=eval('('+g+')');return typeof j==='function'?h({'':i},''):i}throw new SyntaxError('JSON.parse');}}}());Faye.XHRTransport=Faye.Class(Faye.Transport,{request:function(b,c,d){Faye.XHR.request('post',this._4,Faye.toJSON(b),function(a){if(c)c.call(d,JSON.parse(a.text()))})}});Faye.XHRTransport.isUsable=function(a){return Faye.URI.parse(a).isLocal()};Faye.Transport.register('long-polling',Faye.XHRTransport);Faye.JSONPTransport=Faye.extend(Faye.Class(Faye.Transport,{request:function(b,c,d){var f={message:Faye.toJSON(b)},g=document.getElementsByTagName('head')[0],j=document.createElement('script'),i=Faye.JSONPTransport.getCallbackName(),h=Faye.URI.parse(this._4,f);Faye.ENV[i]=function(a){Faye.ENV[i]=undefined;try{delete Faye.ENV[i]}catch(e){}g.removeChild(j);if(c)c.call(d,a)};h.params.jsonp=i;j.type='text/javascript';j.src=h.toURL();g.appendChild(j)}}),{_v:0,getCallbackName:function(){this._v+=1;return'__jsonp'+this._v+'__'}});Faye.JSONPTransport.isUsable=function(a){return true};Faye.Transport.register('callback-polling',Faye.JSONPTransport);
|
data/build/faye.js
CHANGED
@@ -12,7 +12,7 @@ Faye.extend = function(dest, source, overwrite) {
|
|
12
12
|
};
|
13
13
|
|
14
14
|
Faye.extend(Faye, {
|
15
|
-
VERSION: '0.3.
|
15
|
+
VERSION: '0.3.2',
|
16
16
|
|
17
17
|
BAYEUX_VERSION: '1.0',
|
18
18
|
ID_LENGTH: 128,
|
@@ -143,6 +143,35 @@ Faye.extend(Faye, {
|
|
143
143
|
});
|
144
144
|
return result;
|
145
145
|
}
|
146
|
+
},
|
147
|
+
|
148
|
+
// http://assanka.net/content/tech/2009/09/02/json2-js-vs-prototype/
|
149
|
+
toJSON: function(object) {
|
150
|
+
if (this.stringify)
|
151
|
+
return this.stringify(object, function(key, value) {
|
152
|
+
return (this[key] instanceof Array)
|
153
|
+
? this[key]
|
154
|
+
: value;
|
155
|
+
});
|
156
|
+
|
157
|
+
return JSON.stringify(object);
|
158
|
+
},
|
159
|
+
|
160
|
+
timestamp: function() {
|
161
|
+
var date = new Date(),
|
162
|
+
year = date.getFullYear(),
|
163
|
+
month = date.getMonth() + 1,
|
164
|
+
day = date.getDate(),
|
165
|
+
hour = date.getHours(),
|
166
|
+
minute = date.getMinutes(),
|
167
|
+
second = date.getSeconds();
|
168
|
+
|
169
|
+
var pad = function(n) {
|
170
|
+
return n < 10 ? '0' + n : String(n);
|
171
|
+
};
|
172
|
+
|
173
|
+
return pad(year) + '-' + pad(month) + '-' + pad(day) + ' ' +
|
174
|
+
pad(hour) + ':' + pad(minute) + ':' + pad(second);
|
146
175
|
}
|
147
176
|
});
|
148
177
|
|
@@ -233,6 +262,72 @@ Faye.Observable = {
|
|
233
262
|
};
|
234
263
|
|
235
264
|
|
265
|
+
Faye.Logging = {
|
266
|
+
LOG_LEVELS: {
|
267
|
+
error: 3,
|
268
|
+
warn: 2,
|
269
|
+
info: 1,
|
270
|
+
debug: 0
|
271
|
+
},
|
272
|
+
|
273
|
+
logLevel: 'error',
|
274
|
+
|
275
|
+
log: function(message, level) {
|
276
|
+
if (!Faye.logger) return;
|
277
|
+
|
278
|
+
var levels = Faye.Logging.LOG_LEVELS;
|
279
|
+
if (levels[Faye.Logging.logLevel] > levels[level]) return;
|
280
|
+
|
281
|
+
var banner = '[' + level.toUpperCase() + '] [Faye',
|
282
|
+
klass = null;
|
283
|
+
|
284
|
+
for (var key in Faye) {
|
285
|
+
if (klass) continue;
|
286
|
+
if (typeof Faye[key] !== 'function') continue;
|
287
|
+
if (this instanceof Faye[key]) klass = key;
|
288
|
+
}
|
289
|
+
if (klass) banner += '.' + klass;
|
290
|
+
banner += '] ';
|
291
|
+
|
292
|
+
Faye.logger(Faye.timestamp() + ' ' + banner + message);
|
293
|
+
},
|
294
|
+
|
295
|
+
error: function(message) {
|
296
|
+
this.log(message, 'error');
|
297
|
+
},
|
298
|
+
warn: function(message) {
|
299
|
+
this.log(message, 'warn');
|
300
|
+
},
|
301
|
+
info: function(message) {
|
302
|
+
this.log(message, 'info');
|
303
|
+
},
|
304
|
+
debug: function(message) {
|
305
|
+
this.log(message, 'debug');
|
306
|
+
}
|
307
|
+
};
|
308
|
+
|
309
|
+
|
310
|
+
Faye.Timeouts = {
|
311
|
+
addTimeout: function(name, delay, callback, scope) {
|
312
|
+
this._timeouts = this._timeouts || {};
|
313
|
+
if (this._timeouts.hasOwnProperty(name)) return;
|
314
|
+
var self = this;
|
315
|
+
this._timeouts[name] = setTimeout(function() {
|
316
|
+
delete self._timeouts[name];
|
317
|
+
callback.call(scope);
|
318
|
+
}, 1000 * delay);
|
319
|
+
},
|
320
|
+
|
321
|
+
removeTimeout: function(name) {
|
322
|
+
this._timeouts = this._timeouts || {};
|
323
|
+
var timeout = this._timeouts[name];
|
324
|
+
if (!timeout) return;
|
325
|
+
clearTimeout(timeout);
|
326
|
+
delete this._timeouts[name];
|
327
|
+
}
|
328
|
+
};
|
329
|
+
|
330
|
+
|
236
331
|
Faye.Channel = Faye.Class({
|
237
332
|
initialize: function(name) {
|
238
333
|
this.__id = this.name = name;
|
@@ -300,6 +395,10 @@ Faye.extend(Faye.Channel, {
|
|
300
395
|
if (this._value !== undefined) block.call(context, prefix, this._value);
|
301
396
|
},
|
302
397
|
|
398
|
+
getKeys: function() {
|
399
|
+
return this.map(function(key, value) { return '/' + key.join('/') });
|
400
|
+
},
|
401
|
+
|
303
402
|
map: function(block, context) {
|
304
403
|
var result = [];
|
305
404
|
this.each([], function(path, value) {
|
@@ -389,6 +488,7 @@ Faye.Namespace = Faye.Class({
|
|
389
488
|
|
390
489
|
Faye.Transport = Faye.extend(Faye.Class({
|
391
490
|
initialize: function(client, endpoint) {
|
491
|
+
this.debug('Created new transport for ' + endpoint);
|
392
492
|
this._client = client;
|
393
493
|
this._endpoint = endpoint;
|
394
494
|
},
|
@@ -397,20 +497,34 @@ Faye.Transport = Faye.extend(Faye.Class({
|
|
397
497
|
if (!(message instanceof Array) && !message.id)
|
398
498
|
message.id = this._client._namespace.generate();
|
399
499
|
|
500
|
+
this.debug('Client ' + this._client._clientId +
|
501
|
+
' sending message to ' + this._endpoint + ': ' +
|
502
|
+
Faye.toJSON(message));
|
503
|
+
|
400
504
|
this.request(message, function(responses) {
|
505
|
+
this.debug('Client ' + this._client._clientId +
|
506
|
+
' received from ' + this._endpoint + ': ' +
|
507
|
+
Faye.toJSON(responses));
|
508
|
+
|
401
509
|
if (!callback) return;
|
510
|
+
|
511
|
+
var messages = [], deliverable = true;
|
402
512
|
Faye.each([].concat(responses), function(response) {
|
403
|
-
|
404
|
-
if (response.id === message.id)
|
405
|
-
callback.call(scope, response)
|
513
|
+
|
514
|
+
if (response.id === message.id) {
|
515
|
+
if (callback.call(scope, response) === false)
|
516
|
+
deliverable = false;
|
517
|
+
}
|
406
518
|
|
407
519
|
if (response.advice)
|
408
520
|
this._client.handleAdvice(response.advice);
|
409
521
|
|
410
522
|
if (response.data && response.channel)
|
411
|
-
|
523
|
+
messages.push(response);
|
412
524
|
|
413
525
|
}, this);
|
526
|
+
|
527
|
+
if (deliverable) this._client.deliverMessages(messages);
|
414
528
|
}, this);
|
415
529
|
}
|
416
530
|
}), {
|
@@ -444,23 +558,32 @@ Faye.Transport = Faye.extend(Faye.Class({
|
|
444
558
|
}
|
445
559
|
});
|
446
560
|
|
561
|
+
Faye.extend(Faye.Transport.prototype, Faye.Logging);
|
562
|
+
|
447
563
|
|
448
564
|
Faye.Client = Faye.Class({
|
449
|
-
UNCONNECTED:
|
450
|
-
CONNECTING:
|
451
|
-
CONNECTED:
|
452
|
-
DISCONNECTED:
|
565
|
+
UNCONNECTED: 1,
|
566
|
+
CONNECTING: 2,
|
567
|
+
CONNECTED: 3,
|
568
|
+
DISCONNECTED: 4,
|
569
|
+
|
570
|
+
HANDSHAKE: 'handshake',
|
571
|
+
RETRY: 'retry',
|
572
|
+
NONE: 'none',
|
453
573
|
|
454
|
-
|
455
|
-
RETRY: 'retry',
|
456
|
-
NONE: 'none',
|
574
|
+
CONNECTION_TIMEOUT: 60.0,
|
457
575
|
|
458
|
-
DEFAULT_ENDPOINT:
|
459
|
-
MAX_DELAY:
|
460
|
-
INTERVAL:
|
576
|
+
DEFAULT_ENDPOINT: '/bayeux',
|
577
|
+
MAX_DELAY: 0.1,
|
578
|
+
INTERVAL: 1000.0,
|
461
579
|
|
462
|
-
initialize: function(endpoint) {
|
580
|
+
initialize: function(endpoint, options) {
|
581
|
+
this.info('New client created for ' + endpoint);
|
582
|
+
|
463
583
|
this._endpoint = endpoint || this.DEFAULT_ENDPOINT;
|
584
|
+
this._options = options || {};
|
585
|
+
this._timeout = this._options.timeout || this.CONNECTION_TIMEOUT;
|
586
|
+
|
464
587
|
this._transport = Faye.Transport.get(this);
|
465
588
|
this._state = this.UNCONNECTED;
|
466
589
|
this._namespace = new Faye.Namespace();
|
@@ -500,6 +623,8 @@ Faye.Client = Faye.Class({
|
|
500
623
|
this._state = this.CONNECTING;
|
501
624
|
var self = this;
|
502
625
|
|
626
|
+
this.info('Initiating handshake with ' + this._endpoint);
|
627
|
+
|
503
628
|
this._transport.send({
|
504
629
|
channel: Faye.Channel.HANDSHAKE,
|
505
630
|
version: Faye.BAYEUX_VERSION,
|
@@ -508,6 +633,7 @@ Faye.Client = Faye.Class({
|
|
508
633
|
}, function(response) {
|
509
634
|
|
510
635
|
if (!response.successful) {
|
636
|
+
this.info('Handshake unsuccessful');
|
511
637
|
setTimeout(function() { self.handshake(callback, scope) }, this._advice.interval);
|
512
638
|
return this._state = this.UNCONNECTED;
|
513
639
|
}
|
@@ -516,6 +642,7 @@ Faye.Client = Faye.Class({
|
|
516
642
|
this._clientId = response.clientId;
|
517
643
|
this._transport = Faye.Transport.get(this, response.supportedConnectionTypes);
|
518
644
|
|
645
|
+
this.info('Handshake successful: ' + this._clientId);
|
519
646
|
if (callback) callback.call(scope);
|
520
647
|
}, this);
|
521
648
|
},
|
@@ -533,14 +660,17 @@ Faye.Client = Faye.Class({
|
|
533
660
|
if (this._advice.reconnect === this.NONE) return;
|
534
661
|
if (this._state === this.DISCONNECTED) return;
|
535
662
|
|
536
|
-
if (this._advice.reconnect === this.HANDSHAKE || this._state === this.UNCONNECTED)
|
663
|
+
if (this._advice.reconnect === this.HANDSHAKE || this._state === this.UNCONNECTED) {
|
664
|
+
this._beginReconnectTimeout();
|
537
665
|
return this.handshake(function() { this.connect(callback, scope) }, this);
|
666
|
+
}
|
538
667
|
|
539
668
|
if (this._state === this.CONNECTING)
|
540
669
|
return this.callback(callback, scope);
|
541
670
|
|
542
671
|
if (this._state !== this.CONNECTED) return;
|
543
672
|
|
673
|
+
this.info('Calling deferred actions for ' + this._clientId);
|
544
674
|
this.setDeferredStatus('succeeded');
|
545
675
|
this.setDeferredStatus('deferred');
|
546
676
|
if (callback) callback.call(scope);
|
@@ -548,6 +678,7 @@ Faye.Client = Faye.Class({
|
|
548
678
|
if (this._connectionId) return;
|
549
679
|
this._connectionId = this._namespace.generate();
|
550
680
|
var self = this;
|
681
|
+
this.info('Initiating connection for ' + this._clientId);
|
551
682
|
|
552
683
|
this._transport.send({
|
553
684
|
channel: Faye.Channel.CONNECT,
|
@@ -555,10 +686,15 @@ Faye.Client = Faye.Class({
|
|
555
686
|
connectionType: this._transport.connectionType,
|
556
687
|
id: this._connectionId
|
557
688
|
|
558
|
-
}, function(response) {
|
689
|
+
}, this._verifyClientId(function(response) {
|
559
690
|
delete this._connectionId;
|
691
|
+
this.removeTimeout('reconnect');
|
692
|
+
|
693
|
+
this.info('Closed connection for ' + this._clientId);
|
560
694
|
setTimeout(function() { self.connect() }, this._advice.interval);
|
561
|
-
}
|
695
|
+
}));
|
696
|
+
|
697
|
+
this._beginReconnectTimeout();
|
562
698
|
},
|
563
699
|
|
564
700
|
// Request Response
|
@@ -572,11 +708,14 @@ Faye.Client = Faye.Class({
|
|
572
708
|
if (this._state !== this.CONNECTED) return;
|
573
709
|
this._state = this.DISCONNECTED;
|
574
710
|
|
711
|
+
this.info('Disconnecting ' + this._clientId);
|
712
|
+
|
575
713
|
this._transport.send({
|
576
714
|
channel: Faye.Channel.DISCONNECT,
|
577
715
|
clientId: this._clientId
|
578
716
|
});
|
579
717
|
|
718
|
+
this.info('Clearing channel listeners for ' + this._clientId);
|
580
719
|
this._channels = new Faye.Channel.Tree();
|
581
720
|
},
|
582
721
|
|
@@ -596,19 +735,25 @@ Faye.Client = Faye.Class({
|
|
596
735
|
channels = [].concat(channels);
|
597
736
|
this._validateChannels(channels);
|
598
737
|
|
738
|
+
this.info('Client ' + this._clientId + ' attempting to subscribe to [' +
|
739
|
+
channels.join(', ') + ']');
|
740
|
+
|
599
741
|
this._transport.send({
|
600
742
|
channel: Faye.Channel.SUBSCRIBE,
|
601
743
|
clientId: this._clientId,
|
602
744
|
subscription: channels
|
603
745
|
|
604
|
-
}, function(response) {
|
605
|
-
if (!response.successful) return;
|
746
|
+
}, this._verifyClientId(function(response) {
|
747
|
+
if (!response.successful || !callback) return;
|
606
748
|
|
749
|
+
this.info('Subscription acknowledged for ' + this._clientId + ' to [' +
|
750
|
+
channels.join(', ') + ']');
|
751
|
+
|
607
752
|
channels = [].concat(response.subscription);
|
608
753
|
Faye.each(channels, function(channel) {
|
609
754
|
this._channels.set(channel, [callback, scope]);
|
610
755
|
}, this);
|
611
|
-
}
|
756
|
+
}));
|
612
757
|
|
613
758
|
}, this);
|
614
759
|
},
|
@@ -629,19 +774,25 @@ Faye.Client = Faye.Class({
|
|
629
774
|
channels = [].concat(channels);
|
630
775
|
this._validateChannels(channels);
|
631
776
|
|
777
|
+
this.info('Client ' + this._clientId + ' attempting to unsubscribe from [' +
|
778
|
+
channels.join(', ') + ']');
|
779
|
+
|
632
780
|
this._transport.send({
|
633
781
|
channel: Faye.Channel.UNSUBSCRIBE,
|
634
782
|
clientId: this._clientId,
|
635
783
|
subscription: channels
|
636
784
|
|
637
|
-
}, function(response) {
|
785
|
+
}, this._verifyClientId(function(response) {
|
638
786
|
if (!response.successful) return;
|
639
787
|
|
788
|
+
this.info('Unsubscription acknowledged for ' + this._clientId + ' from [' +
|
789
|
+
channels.join(', ') + ']');
|
790
|
+
|
640
791
|
channels = [].concat(response.subscription);
|
641
792
|
Faye.each(channels, function(channel) {
|
642
793
|
this._channels.set(channel, null);
|
643
794
|
}, this);
|
644
|
-
}
|
795
|
+
}));
|
645
796
|
|
646
797
|
}, this);
|
647
798
|
},
|
@@ -657,19 +808,16 @@ Faye.Client = Faye.Class({
|
|
657
808
|
|
658
809
|
this._validateChannels([channel]);
|
659
810
|
|
811
|
+
this.info('Client ' + this._clientId + ' queueing published message to ' +
|
812
|
+
channel + ': ' + Faye.toJSON(data));
|
813
|
+
|
660
814
|
this._enqueue({
|
661
815
|
channel: channel,
|
662
816
|
data: data,
|
663
817
|
clientId: this._clientId
|
664
818
|
});
|
665
819
|
|
666
|
-
|
667
|
-
var self = this;
|
668
|
-
|
669
|
-
this._timeout = setTimeout(function() {
|
670
|
-
delete self._timeout;
|
671
|
-
self._flush();
|
672
|
-
}, this.MAX_DELAY * 1000);
|
820
|
+
this.addTimeout('publish', this.MAX_DELAY, this._flush, this);
|
673
821
|
|
674
822
|
}, this);
|
675
823
|
},
|
@@ -679,12 +827,30 @@ Faye.Client = Faye.Class({
|
|
679
827
|
if (this._advice.reconnect === this.HANDSHAKE) this._clientId = null;
|
680
828
|
},
|
681
829
|
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
830
|
+
deliverMessages: function(messages) {
|
831
|
+
Faye.each(messages, function(message) {
|
832
|
+
this.info('Client ' + this._clientId + ' calling listeners for ' +
|
833
|
+
message.channel + ' with ' + Faye.toJSON(message.data));
|
834
|
+
|
835
|
+
var channels = this._channels.glob(message.channel);
|
836
|
+
Faye.each(channels, function(callback) {
|
837
|
+
if (!callback) return;
|
838
|
+
callback[0].call(callback[1], message.data);
|
839
|
+
});
|
840
|
+
}, this);
|
841
|
+
},
|
842
|
+
|
843
|
+
_beginReconnectTimeout: function() {
|
844
|
+
this.addTimeout('reconnect', this._timeout, function() {
|
845
|
+
delete this._connectionId;
|
846
|
+
delete this._clientId;
|
847
|
+
this._state = this.UNCONNECTED;
|
848
|
+
|
849
|
+
this.info('Server took >' + this._timeout + 's to reply to connection for ' +
|
850
|
+
this._clientId + ': attempting to reconnect');
|
851
|
+
|
852
|
+
this.subscribe(this._channels.getKeys());
|
853
|
+
}, this);
|
688
854
|
},
|
689
855
|
|
690
856
|
_enqueue: function(message) {
|
@@ -703,10 +869,21 @@ Faye.Client = Faye.Class({
|
|
703
869
|
if (!Faye.Channel.isSubscribable(channel))
|
704
870
|
throw 'Clients may not subscribe to channel "' + channel + '"';
|
705
871
|
});
|
872
|
+
},
|
873
|
+
|
874
|
+
_verifyClientId: function(callback) {
|
875
|
+
var self = this;
|
876
|
+
return function(response) {
|
877
|
+
if (response.clientId !== self._clientId) return false;
|
878
|
+
callback.call(self, response);
|
879
|
+
return true;
|
880
|
+
};
|
706
881
|
}
|
707
882
|
});
|
708
883
|
|
709
884
|
Faye.extend(Faye.Client.prototype, Faye.Deferrable);
|
885
|
+
Faye.extend(Faye.Client.prototype, Faye.Timeouts);
|
886
|
+
Faye.extend(Faye.Client.prototype, Faye.Logging);
|
710
887
|
|
711
888
|
|
712
889
|
Faye.Set = Faye.Class({
|
@@ -757,6 +934,7 @@ Faye.Set = Faye.Class({
|
|
757
934
|
|
758
935
|
Faye.Server = Faye.Class({
|
759
936
|
initialize: function(options) {
|
937
|
+
this.info('New server created');
|
760
938
|
this._options = options || {};
|
761
939
|
this._channels = new Faye.Channel.Tree();
|
762
940
|
this._clients = {};
|
@@ -770,6 +948,8 @@ Faye.Server = Faye.Class({
|
|
770
948
|
},
|
771
949
|
|
772
950
|
process: function(messages, local, callback) {
|
951
|
+
this.debug('Processing messages from ' + (local ? 'LOCAL' : 'REMOTE') + ' client');
|
952
|
+
|
773
953
|
messages = [].concat(messages);
|
774
954
|
var processed = 0, responses = [];
|
775
955
|
|
@@ -777,8 +957,9 @@ Faye.Server = Faye.Class({
|
|
777
957
|
this._handle(message, local, function(reply) {
|
778
958
|
responses = responses.concat(reply);
|
779
959
|
processed += 1;
|
780
|
-
if (processed
|
781
|
-
|
960
|
+
if (processed < messages.length) return;
|
961
|
+
callback(responses);
|
962
|
+
}, this);
|
782
963
|
}, this);
|
783
964
|
},
|
784
965
|
|
@@ -803,42 +984,54 @@ Faye.Server = Faye.Class({
|
|
803
984
|
delete this._clients[client.id];
|
804
985
|
},
|
805
986
|
|
806
|
-
_handle: function(message, local, callback) {
|
807
|
-
var
|
808
|
-
channel = message.channel,
|
987
|
+
_handle: function(message, local, callback, scope) {
|
988
|
+
var channel = message.channel,
|
809
989
|
response;
|
810
990
|
|
811
991
|
message.__id = Faye.random();
|
812
|
-
Faye.each(this._channels.glob(channel), function(c) {
|
992
|
+
Faye.each(this._channels.glob(channel), function(c) {
|
993
|
+
c.push(message);
|
994
|
+
this.info('Publishing message ' + Faye.toJSON(message.data) +
|
995
|
+
' from client ' + clientId + ' to ' + c.name);
|
996
|
+
}, this);
|
813
997
|
|
814
998
|
if (Faye.Channel.isMeta(channel)) {
|
815
999
|
response = this[Faye.Channel.parse(channel)[1]](message, local);
|
816
1000
|
|
817
|
-
clientId =
|
1001
|
+
var clientId = response.clientId;
|
818
1002
|
response.advice = response.advice || {};
|
819
1003
|
Faye.extend(response.advice, {
|
820
1004
|
reconnect: this._clients.hasOwnProperty(clientId) ? 'retry' : 'handshake',
|
821
|
-
interval: Faye.Connection.INTERVAL * 1000
|
1005
|
+
interval: Math.floor(Faye.Connection.prototype.INTERVAL * 1000)
|
822
1006
|
}, false);
|
823
1007
|
|
824
|
-
response.id = message.id;
|
825
|
-
|
826
1008
|
if (response.channel !== Faye.Channel.CONNECT ||
|
827
1009
|
response.successful !== true)
|
828
|
-
return callback(response);
|
1010
|
+
return callback.call(scope, response);
|
829
1011
|
|
1012
|
+
this.info('Accepting connection from ' + response.clientId);
|
830
1013
|
return this._connection(response.clientId).connect(function(events) {
|
1014
|
+
this.info('Sending event messages to ' + response.clientId);
|
1015
|
+
this.debug('Events for ' + response.clientId + ': ' + Faye.toJSON(events));
|
831
1016
|
Faye.each(events, function(e) { delete e.__id });
|
832
|
-
callback([response].concat(events));
|
833
|
-
});
|
1017
|
+
callback.call(scope, [response].concat(events));
|
1018
|
+
}, this);
|
834
1019
|
}
|
835
1020
|
|
836
1021
|
if (!message.clientId || Faye.Channel.isService(channel))
|
837
1022
|
return callback([]);
|
838
1023
|
|
839
|
-
|
840
|
-
|
841
|
-
|
1024
|
+
response = this._makeResponse(message);
|
1025
|
+
response.successful = true;
|
1026
|
+
callback(response);
|
1027
|
+
},
|
1028
|
+
|
1029
|
+
_makeResponse: function(message) {
|
1030
|
+
var response = {};
|
1031
|
+
Faye.each(['id', 'clientId', 'channel'], function(field) {
|
1032
|
+
if (message[field]) response[field] = message[field];
|
1033
|
+
});
|
1034
|
+
return response;
|
842
1035
|
},
|
843
1036
|
|
844
1037
|
// MUST contain * version
|
@@ -847,9 +1040,8 @@ Faye.Server = Faye.Class({
|
|
847
1040
|
// * ext
|
848
1041
|
// * id
|
849
1042
|
handshake: function(message, local) {
|
850
|
-
var response =
|
851
|
-
|
852
|
-
id: message.id };
|
1043
|
+
var response = this._makeResponse(message);
|
1044
|
+
response.version = Faye.BAYEUX_VERSION;
|
853
1045
|
|
854
1046
|
if (!message.version)
|
855
1047
|
response.error = Faye.Error.parameterMissing('version');
|
@@ -876,6 +1068,7 @@ Faye.Server = Faye.Class({
|
|
876
1068
|
|
877
1069
|
var clientId = this._namespace.generate();
|
878
1070
|
response.clientId = this._connection(clientId).id;
|
1071
|
+
this.info('Accepting handshake from client ' + response.clientId);
|
879
1072
|
return response;
|
880
1073
|
},
|
881
1074
|
|
@@ -884,8 +1077,7 @@ Faye.Server = Faye.Class({
|
|
884
1077
|
// MAY contain * ext
|
885
1078
|
// * id
|
886
1079
|
connect: function(message, local) {
|
887
|
-
var response =
|
888
|
-
id: message.id };
|
1080
|
+
var response = this._makeResponse(message);
|
889
1081
|
|
890
1082
|
var clientId = message.clientId,
|
891
1083
|
client = clientId ? this._clients[clientId] : null,
|
@@ -896,6 +1088,7 @@ Faye.Server = Faye.Class({
|
|
896
1088
|
if (!connectionType) response.error = Faye.Error.parameterMissing('connectionType');
|
897
1089
|
|
898
1090
|
response.successful = !response.error;
|
1091
|
+
if (!response.successful) delete response.clientId;
|
899
1092
|
if (!response.successful) return response;
|
900
1093
|
|
901
1094
|
response.clientId = client.id;
|
@@ -906,8 +1099,7 @@ Faye.Server = Faye.Class({
|
|
906
1099
|
// MAY contain * ext
|
907
1100
|
// * id
|
908
1101
|
disconnect: function(message, local) {
|
909
|
-
var response =
|
910
|
-
id: message.id };
|
1102
|
+
var response = this._makeResponse(message);
|
911
1103
|
|
912
1104
|
var clientId = message.clientId,
|
913
1105
|
client = clientId ? this._clients[clientId] : null;
|
@@ -916,10 +1108,12 @@ Faye.Server = Faye.Class({
|
|
916
1108
|
if (!clientId) response.error = Faye.Error.parameterMissing('clientId');
|
917
1109
|
|
918
1110
|
response.successful = !response.error;
|
1111
|
+
if (!response.successful) delete response.clientId;
|
919
1112
|
if (!response.successful) return response;
|
920
1113
|
|
921
1114
|
this._destroyClient(client);
|
922
1115
|
|
1116
|
+
this.info('Disconnected client: ' + clientId);
|
923
1117
|
response.clientId = clientId;
|
924
1118
|
return response;
|
925
1119
|
},
|
@@ -929,9 +1123,7 @@ Faye.Server = Faye.Class({
|
|
929
1123
|
// MAY contain * ext
|
930
1124
|
// * id
|
931
1125
|
subscribe: function(message, local) {
|
932
|
-
var response
|
933
|
-
clientId: message.clientId,
|
934
|
-
id: message.id };
|
1126
|
+
var response = this._makeResponse(message);
|
935
1127
|
|
936
1128
|
var clientId = message.clientId,
|
937
1129
|
client = clientId ? this._clients[clientId] : null,
|
@@ -952,6 +1144,8 @@ Faye.Server = Faye.Class({
|
|
952
1144
|
|
953
1145
|
if (response.error) return;
|
954
1146
|
channel = this._channels.findOrCreate(channel);
|
1147
|
+
|
1148
|
+
this.info('Subscribing client ' + clientId + ' to ' + channel.name);
|
955
1149
|
client.subscribe(channel);
|
956
1150
|
}, this);
|
957
1151
|
|
@@ -964,9 +1158,7 @@ Faye.Server = Faye.Class({
|
|
964
1158
|
// MAY contain * ext
|
965
1159
|
// * id
|
966
1160
|
unsubscribe: function(message, local) {
|
967
|
-
var response
|
968
|
-
clientId: message.clientId,
|
969
|
-
id: message.id };
|
1161
|
+
var response = this._makeResponse(message);
|
970
1162
|
|
971
1163
|
var clientId = message.clientId,
|
972
1164
|
client = clientId ? this._clients[clientId] : null,
|
@@ -985,7 +1177,10 @@ Faye.Server = Faye.Class({
|
|
985
1177
|
return response.error = Faye.Error.channelInvalid(channel);
|
986
1178
|
|
987
1179
|
channel = this._channels.get(channel);
|
988
|
-
if (channel)
|
1180
|
+
if (!channel) return;
|
1181
|
+
|
1182
|
+
this.info('Unsubscribing client ' + clientId + ' from ' + channel.name);
|
1183
|
+
client.unsubscribe(channel);
|
989
1184
|
}, this);
|
990
1185
|
|
991
1186
|
response.successful = !response.error;
|
@@ -993,6 +1188,8 @@ Faye.Server = Faye.Class({
|
|
993
1188
|
}
|
994
1189
|
});
|
995
1190
|
|
1191
|
+
Faye.extend(Faye.Server.prototype, Faye.Logging);
|
1192
|
+
|
996
1193
|
|
997
1194
|
Faye.Connection = Faye.Class({
|
998
1195
|
MAX_DELAY: 0.1,
|
@@ -1002,12 +1199,10 @@ Faye.Connection = Faye.Class({
|
|
1002
1199
|
initialize: function(id, options) {
|
1003
1200
|
this.id = id;
|
1004
1201
|
this._options = options;
|
1202
|
+
this._timeout = this._options.timeout || this.TIMEOUT;
|
1005
1203
|
this._channels = new Faye.Set();
|
1006
1204
|
this._inbox = new Faye.Set();
|
1007
|
-
|
1008
|
-
|
1009
|
-
getTimeout: function() {
|
1010
|
-
return this._options.timeout || this.TIMEOUT;
|
1205
|
+
this._connected = false
|
1011
1206
|
},
|
1012
1207
|
|
1013
1208
|
_onMessage: function(event) {
|
@@ -1027,16 +1222,12 @@ Faye.Connection = Faye.Class({
|
|
1027
1222
|
channel.stopObserving('message', this._onMessage, this);
|
1028
1223
|
},
|
1029
1224
|
|
1030
|
-
connect: function(callback) {
|
1031
|
-
this.callback(callback);
|
1225
|
+
connect: function(callback, scope) {
|
1226
|
+
this.callback(callback, scope);
|
1032
1227
|
if (this._connected) return;
|
1033
1228
|
|
1034
1229
|
this._connected = true;
|
1035
|
-
|
1036
|
-
if (this._deletionTimeout) {
|
1037
|
-
clearTimeout(this._deletionTimeout);
|
1038
|
-
delete this._deletionTimeout;
|
1039
|
-
}
|
1230
|
+
this.removeTimeout('deletion');
|
1040
1231
|
|
1041
1232
|
this._beginDeliveryTimeout();
|
1042
1233
|
this._beginConnectionTimeout();
|
@@ -1059,50 +1250,29 @@ Faye.Connection = Faye.Class({
|
|
1059
1250
|
},
|
1060
1251
|
|
1061
1252
|
_beginDeliveryTimeout: function() {
|
1062
|
-
if (
|
1063
|
-
|
1064
|
-
|
1065
|
-
var self = this;
|
1066
|
-
this._deliveryTimeout = setTimeout(function () { self.flush() },
|
1067
|
-
this.MAX_DELAY * 1000);
|
1253
|
+
if (!this._connected || this._inbox.isEmpty()) return;
|
1254
|
+
this.addTimeout('delivery', this.MAX_DELAY, this.flush, this);
|
1068
1255
|
},
|
1069
1256
|
|
1070
1257
|
_beginConnectionTimeout: function() {
|
1071
|
-
if (
|
1072
|
-
|
1073
|
-
|
1074
|
-
var self = this;
|
1075
|
-
this._connectionTimeout = setTimeout(function() { self.flush() },
|
1076
|
-
this.getTimeout() * 1000);
|
1258
|
+
if (!this._connected) return;
|
1259
|
+
this.addTimeout('connection', this._timeout, this.flush, this);
|
1077
1260
|
},
|
1078
1261
|
|
1079
1262
|
_releaseConnection: function() {
|
1080
|
-
|
1081
|
-
|
1082
|
-
delete this._connectionTimeout;
|
1083
|
-
}
|
1084
|
-
|
1085
|
-
if (this._deliveryTimeout) {
|
1086
|
-
clearTimeout(this._deliveryTimeout);
|
1087
|
-
delete this._deliveryTimeout;
|
1088
|
-
}
|
1089
|
-
|
1263
|
+
this.removeTimeout('connection');
|
1264
|
+
this.removeTimeout('delivery');
|
1090
1265
|
this._connected = false;
|
1091
|
-
this._scheduleForDeletion();
|
1092
|
-
},
|
1093
|
-
|
1094
|
-
_scheduleForDeletion: function() {
|
1095
|
-
if (this._deletionTimeout) return;
|
1096
|
-
var self = this;
|
1097
1266
|
|
1098
|
-
this.
|
1099
|
-
|
1100
|
-
},
|
1267
|
+
this.addTimeout('deletion', 10 * this.INTERVAL, function() {
|
1268
|
+
this.fire('staleClient', this);
|
1269
|
+
}, this);
|
1101
1270
|
}
|
1102
1271
|
});
|
1103
1272
|
|
1104
1273
|
Faye.extend(Faye.Connection.prototype, Faye.Deferrable);
|
1105
1274
|
Faye.extend(Faye.Connection.prototype, Faye.Observable);
|
1275
|
+
Faye.extend(Faye.Connection.prototype, Faye.Timeouts);
|
1106
1276
|
|
1107
1277
|
|
1108
1278
|
Faye.Error = Faye.Class({
|
@@ -1170,53 +1340,6 @@ Faye.Error.serverError = function() {
|
|
1170
1340
|
|
1171
1341
|
|
1172
1342
|
|
1173
|
-
Faye.NodeHttpTransport = Faye.Class(Faye.Transport, {
|
1174
|
-
request: function(message, callback, scope) {
|
1175
|
-
var params = {message: JSON.stringify(message)},
|
1176
|
-
request = this.createRequest();
|
1177
|
-
|
1178
|
-
request.write(querystring.stringify(params));
|
1179
|
-
|
1180
|
-
request.addListener('response', function(response) {
|
1181
|
-
if (!callback) return;
|
1182
|
-
response.addListener('data', function(chunk) {
|
1183
|
-
callback.call(scope, JSON.parse(chunk));
|
1184
|
-
});
|
1185
|
-
});
|
1186
|
-
request.close();
|
1187
|
-
},
|
1188
|
-
|
1189
|
-
createRequest: function() {
|
1190
|
-
var uri = url.parse(this._endpoint),
|
1191
|
-
client = http.createClient(uri.port, uri.hostname);
|
1192
|
-
|
1193
|
-
return client.request('POST', uri.pathname, {
|
1194
|
-
'Content-Type': 'application/x-www-form-urlencoded'
|
1195
|
-
});
|
1196
|
-
}
|
1197
|
-
});
|
1198
|
-
|
1199
|
-
Faye.NodeHttpTransport.isUsable = function(endpoint) {
|
1200
|
-
return typeof endpoint === 'string';
|
1201
|
-
};
|
1202
|
-
|
1203
|
-
Faye.Transport.register('long-polling', Faye.NodeHttpTransport);
|
1204
|
-
|
1205
|
-
Faye.NodeLocalTransport = Faye.Class(Faye.Transport, {
|
1206
|
-
request: function(message, callback, scope) {
|
1207
|
-
this._endpoint.process(message, true, function(response) {
|
1208
|
-
callback.call(scope, response);
|
1209
|
-
});
|
1210
|
-
}
|
1211
|
-
});
|
1212
|
-
|
1213
|
-
Faye.NodeLocalTransport.isUsable = function(endpoint) {
|
1214
|
-
return endpoint instanceof Faye.Server;
|
1215
|
-
};
|
1216
|
-
|
1217
|
-
Faye.Transport.register('in-process', Faye.NodeLocalTransport);
|
1218
|
-
|
1219
|
-
|
1220
1343
|
var path = require('path'),
|
1221
1344
|
fs = require('fs'),
|
1222
1345
|
sys = require('sys'),
|
@@ -1224,19 +1347,31 @@ var path = require('path'),
|
|
1224
1347
|
http = require('http'),
|
1225
1348
|
querystring = require('querystring');
|
1226
1349
|
|
1350
|
+
Faye.logger = function(message) {
|
1351
|
+
sys.puts(message);
|
1352
|
+
};
|
1353
|
+
|
1354
|
+
Faye.withDataFor = function(transport, callback, scope) {
|
1355
|
+
var data = '';
|
1356
|
+
transport.addListener('data', function(chunk) { data += chunk });
|
1357
|
+
transport.addListener('end', function() {
|
1358
|
+
callback.call(scope, data);
|
1359
|
+
});
|
1360
|
+
};
|
1361
|
+
|
1227
1362
|
Faye.NodeAdapter = Faye.Class({
|
1228
1363
|
DEFAULT_ENDPOINT: '/bayeux',
|
1229
1364
|
SCRIPT_PATH: path.dirname(__filename) + '/faye-client-min.js',
|
1230
1365
|
|
1231
|
-
TYPE_JSON: {'Content-Type': '
|
1366
|
+
TYPE_JSON: {'Content-Type': 'application/json'},
|
1232
1367
|
TYPE_SCRIPT: {'Content-Type': 'text/javascript'},
|
1233
1368
|
TYPE_TEXT: {'Content-Type': 'text/plain'},
|
1234
1369
|
|
1235
1370
|
initialize: function(options) {
|
1236
|
-
this._options
|
1237
|
-
this._endpoint
|
1238
|
-
this.
|
1239
|
-
this._server
|
1371
|
+
this._options = options || {};
|
1372
|
+
this._endpoint = this._options.mount || this.DEFAULT_ENDPOINT;
|
1373
|
+
this._endpointRe = new RegExp('^' + this._endpoint + '(/[^/]+)*(\\.js)?$');
|
1374
|
+
this._server = new Faye.Server(this._options);
|
1240
1375
|
},
|
1241
1376
|
|
1242
1377
|
getClient: function() {
|
@@ -1252,35 +1387,30 @@ Faye.NodeAdapter = Faye.Class({
|
|
1252
1387
|
|
1253
1388
|
call: function(request, response) {
|
1254
1389
|
var requestUrl = url.parse(request.url, true),
|
1255
|
-
self = this;
|
1390
|
+
self = this, data;
|
1391
|
+
|
1392
|
+
if (!this._endpointRe.test(requestUrl.pathname))
|
1393
|
+
return false;
|
1256
1394
|
|
1257
|
-
|
1395
|
+
if (/\.js$/.test(requestUrl.pathname)) {
|
1396
|
+
fs.readFile(this.SCRIPT_PATH, function(err, content) {
|
1397
|
+
response.sendHeader(200, self.TYPE_SCRIPT);
|
1398
|
+
response.write(content);
|
1399
|
+
response.close();
|
1400
|
+
});
|
1258
1401
|
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
if (isGet)
|
1263
|
-
this._callWithParams(request, response, requestUrl.query);
|
1264
|
-
|
1265
|
-
else
|
1266
|
-
request.addListener('data', function(chunk) {
|
1267
|
-
self._callWithParams(request, response, querystring.parse(chunk));
|
1268
|
-
});
|
1269
|
-
|
1270
|
-
return true;
|
1271
|
-
break;
|
1402
|
+
} else {
|
1403
|
+
var isGet = (request.method === 'GET');
|
1272
1404
|
|
1273
|
-
|
1274
|
-
|
1275
|
-
response.sendHeader(200, self.TYPE_SCRIPT);
|
1276
|
-
response.write(content);
|
1277
|
-
response.close();
|
1278
|
-
});
|
1279
|
-
return true;
|
1280
|
-
break;
|
1405
|
+
if (isGet)
|
1406
|
+
this._callWithParams(request, response, requestUrl.query);
|
1281
1407
|
|
1282
|
-
|
1408
|
+
else
|
1409
|
+
Faye.withDataFor(request, function(data) {
|
1410
|
+
self._callWithParams(request, response, {message: data});
|
1411
|
+
});
|
1283
1412
|
}
|
1413
|
+
return true;
|
1284
1414
|
},
|
1285
1415
|
|
1286
1416
|
_callWithParams: function(request, response, params) {
|
@@ -1308,4 +1438,55 @@ Faye.NodeAdapter = Faye.Class({
|
|
1308
1438
|
});
|
1309
1439
|
|
1310
1440
|
exports.NodeAdapter = Faye.NodeAdapter;
|
1311
|
-
exports.Client = Faye.Client;
|
1441
|
+
exports.Client = Faye.Client;
|
1442
|
+
|
1443
|
+
|
1444
|
+
Faye.NodeHttpTransport = Faye.Class(Faye.Transport, {
|
1445
|
+
request: function(message, callback, scope) {
|
1446
|
+
var request = this.createRequestForMessage(message);
|
1447
|
+
|
1448
|
+
request.addListener('response', function(response) {
|
1449
|
+
if (!callback) return;
|
1450
|
+
Faye.withDataFor(response, function(data) {
|
1451
|
+
callback.call(scope, JSON.parse(data));
|
1452
|
+
});
|
1453
|
+
});
|
1454
|
+
request.close();
|
1455
|
+
},
|
1456
|
+
|
1457
|
+
createRequestForMessage: function(message) {
|
1458
|
+
var content = JSON.stringify(message),
|
1459
|
+
uri = url.parse(this._endpoint),
|
1460
|
+
client = http.createClient(uri.port, uri.hostname);
|
1461
|
+
|
1462
|
+
if (parseInt(uri.port) === 443) client.setSecure('X509_PEM');
|
1463
|
+
|
1464
|
+
var request = client.request('POST', uri.pathname, {
|
1465
|
+
'Content-Type': 'application/json',
|
1466
|
+
'host': uri.hostname,
|
1467
|
+
'Content-Length': content.length
|
1468
|
+
});
|
1469
|
+
request.write(content);
|
1470
|
+
return request;
|
1471
|
+
}
|
1472
|
+
});
|
1473
|
+
|
1474
|
+
Faye.NodeHttpTransport.isUsable = function(endpoint) {
|
1475
|
+
return typeof endpoint === 'string';
|
1476
|
+
};
|
1477
|
+
|
1478
|
+
Faye.Transport.register('long-polling', Faye.NodeHttpTransport);
|
1479
|
+
|
1480
|
+
Faye.NodeLocalTransport = Faye.Class(Faye.Transport, {
|
1481
|
+
request: function(message, callback, scope) {
|
1482
|
+
this._endpoint.process(message, true, function(response) {
|
1483
|
+
callback.call(scope, response);
|
1484
|
+
});
|
1485
|
+
}
|
1486
|
+
});
|
1487
|
+
|
1488
|
+
Faye.NodeLocalTransport.isUsable = function(endpoint) {
|
1489
|
+
return endpoint instanceof Faye.Server;
|
1490
|
+
};
|
1491
|
+
|
1492
|
+
Faye.Transport.register('in-process', Faye.NodeLocalTransport);
|