faye 0.1.1 → 0.2.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.

@@ -0,0 +1,6 @@
1
+ require 'sinatra'
2
+ PUBLIC_DIR = File.dirname(__FILE__) + '/../shared/public'
3
+ set :public, PUBLIC_DIR
4
+
5
+ get('/') { File.read(PUBLIC_DIR + '/index.html') }
6
+
@@ -3,6 +3,6 @@ dir = File.dirname(__FILE__)
3
3
  require dir + '/../../lib/faye'
4
4
  require dir + '/app'
5
5
 
6
- use Faye::RackAdapter, :mount => '/comet'
6
+ use Faye::RackAdapter, :mount => '/comet', :timeout => 25
7
7
  run Sinatra::Application
8
8
 
File without changes
File without changes
data/jake.yml CHANGED
@@ -1,19 +1,34 @@
1
1
  ---
2
- source_directory: client
3
- build_directory: lib
2
+ source_directory: javascript
3
+ build_directory: build
4
4
  builds:
5
+ src:
6
+ packer: false
7
+ suffix: false
5
8
  min:
6
9
  shrink_vars: true
7
10
  private: true
8
11
  packages:
9
- faye:
12
+ core:
10
13
  - faye
11
14
  - util/class
12
- - util/event
13
- - util/uri
14
- - util/xhr
15
+ - util/observable
15
16
  - channel
16
- - transport
17
- - client
18
- - util/json
17
+ faye:
18
+ extends: core
19
+ files:
20
+ - util/set
21
+ - server
22
+ - connection
23
+ - error
24
+ - node_adapter
25
+ faye-client:
26
+ extends: core
27
+ files:
28
+ - util/event
29
+ - util/uri
30
+ - util/xhr
31
+ - transport
32
+ - client
33
+ - util/json
19
34
 
@@ -0,0 +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)&&a[d]!==b[d]){if(!a.hasOwnProperty(d)||c!==false)a[d]=b[d]}}return a};Faye.extend(Faye,{BAYEUX_VERSION:'1.0',VERSION:'0.2.2',JSONP_CALLBACK:'jsonpcallback',ID_LENGTH:128,CONNECTION_TYPES:["long-polling","callback-polling"],ENV:this,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])}}},size:function(a){var b=0;this.each(a,function(){b+=1});return b},random:function(){var a=Math.pow(2,this.ID_LENGTH);return(Math.random()*a).toString(16).replace(/0*$/,'')},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.Observable={on:function(a,b,c){this._1=this._1||{};var d=this._1[a]=this._1[a]||[];d.push([b,c])},stopObserving:function(a,b,c){if(!this._1||!this._1[a])return;if(!b){delete this._1[a];return}var d=this._1[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._1||!this._1[c])return;Faye.each(this._1[c],function(a){a[0].apply(a[1],b.slice())})}};Faye.Channel=Faye.Class({initialize:function(a){this.__id=this._A=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._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._3!==undefined)d.call(f,c,this._3)},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._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._3===undefined)?[]:[this._3];var g=[];if(Faye.enumEqual(f,['*'])){Faye.each(this._5,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});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['**']._3);return g}})});Faye.Event={_a:[],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._a.push({_b:a,_h:b,_s:c,_c:d,_m:f})},detach:function(a,b,c,d){var f=this._a.length,g;while(f--){g=this._a[f];if((a&&a!==g._b)||(b&&b!==g._h)||(c&&c!==g._s)||(d&&d!==g._c))continue;if(g._b.removeEventListener)g._b.removeEventListener(g._h,g._m,false);else g._b.detachEvent('on'+g._h,g._m);this._a.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._d=a.toUpperCase();this._6=Faye.URI.parse(b,c);this._t=(typeof d==='function')?{success:d}:d;this._c=f||null;this._2=null},send:function(){if(this._i)return;var a=this._6.pathname,b=this._6.queryString();if(this._d==='GET')a+='?'+b;var c=this._d==='POST'?b:'';this._i=true;this._2=Faye.XHR.getXhrObject();this._2.open(this._d,a,true);if(this._d==='POST')this._2.setRequestHeader('Content-Type','application/x-www-form-urlencoded');var d=this,f=function(){if(d._2.readyState!==4)return;if(g){clearInterval(g);g=null}Faye.Event.detach(Faye.ENV,'beforeunload',d.abort,d);d._i=false;d._u();d=null};var g=setInterval(f,10);Faye.Event.on(Faye.ENV,'beforeunload',this.abort,this);this._2.send(c)},abort:function(){this._2.abort()},_u:function(){var a=this._t;if(!a)return;return this.success()?a.success&&a.success.call(this._c,this):a.failure&&a.failure.call(this._c,this)},waiting:function(){return!!this._i},complete:function(){return this._2&&!this.waiting()},success:function(){if(!this.complete())return false;var a=this._2.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._2.responseText},status:function(){if(!this.complete())return null;return this._2.status}})};Faye.Transport=Faye.extend(Faye.Class({initialize:function(a,b){this._n=a;this._6=b},send:function(c,d,f){c={message:JSON.stringify(c)};return this.request(c,function(b){if(!d)return;Faye.each([].concat(b),function(a){d.call(f,a);if(a.advice)this._n._v(a.advice);if(a.data&&a.channel)this._n._w(a)},this)},this)}}),{get:function(a,b){var c=a._6;if(b===undefined)b=this.supportedConnectionTypes();var d=Faye.URI.parse(c).isLocal()?['long-polling','callback-polling']:['callback-polling'];var f=Faye.commonElement(d,b);if(!f)throw'Could not find a usable connection type for '+c;var g=this._j[f];return new g(a,c)},register:function(a,b){this._j[a]=b;b.prototype.connectionType=a},_j:{},supportedConnectionTypes:function(){var c=[],d;Faye.each(this._j,function(a,b){c.push(a)});return c}});Faye.XHRTransport=Faye.Class(Faye.Transport,{request:function(b,c,d){Faye.XHR.request('post',this._6,b,function(a){if(c)c.call(d,JSON.parse(a.text()))})}});Faye.Transport.register('long-polling',Faye.XHRTransport);Faye.JSONPTransport=Faye.extend(Faye.Class(Faye.Transport,{request:function(b,c,d){var f=document.getElementsByTagName('head')[0],g=document.createElement('script'),k=Faye.JSONPTransport.getCallbackName(),i=Faye.URI.parse(this._6,b);Faye.ENV[k]=function(a){Faye.ENV[k]=undefined;try{delete Faye.ENV[k]}catch(e){}f.removeChild(g);if(c)c.call(d,a)};i.params.jsonp=k;g.type='text/javascript';g.src=i.toURL();f.appendChild(g)}}),{_o:0,getCallbackName:function(){this._o+=1;return'__jsonp'+this._o+'__'}});Faye.Transport.register('callback-polling',Faye.JSONPTransport);Faye.Client=Faye.Class({_e:{},_x:{},_8:{},_y:{},_p:'handshake',_z:'retry',_q:'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._0=this._e;this._k=[];this._f=new Faye.Channel.Tree();this._7={reconnect:this._z,interval:this.INTERVAL};Faye.Event.on(Faye.ENV,'beforeunload',this.disconnect,this)},handshake:function(b,c){if(this._7.reconnect===this._q)return;if(this._0!==this._e)return;this._0=this._x;var d=this,f=this.generateId();this._4.send({channel:Faye.Channel.HANDSHAKE,version:Faye.BAYEUX_VERSION,supportedConnectionTypes:Faye.Transport.supportedConnectionTypes(),id:f},function(a){if(a.id!==f)return;if(!a.successful){setTimeout(function(){d.handshake(b,c)},this._7.interval);return this._0=this._e}this._0=this._8;this._9=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._q)return;if(this._7.reconnect===this._p||this._0===this._e)return this.handshake(function(){this.connect(b,c)},this);if(this._0!==this._8)return;if(this._g)return;this._g=this.generateId();var d=this;this._4.send({channel:Faye.Channel.CONNECT,clientId:this._9,connectionType:this._4.connectionType,id:this._g},function(a){if(a.id!==this._g)return;delete this._g;if(a.successful)this.connect();else setTimeout(function(){d.connect()},this._7.interval)},this);if(b)b.call(c)},disconnect:function(){if(this._0!==this._8)return;this._0=this._y;this._4.send({channel:Faye.Channel.DISCONNECT,clientId:this._9});this._f=new Faye.Channel.Tree()},subscribe:function(c,d,f){if(this._0!==this._8)return;c=[].concat(c);this._l(c);var g=this.generateId();this._4.send({channel:Faye.Channel.SUBSCRIBE,clientId:this._9,subscription:c,id:g},function(b){if(b.id!==g)return;if(!b.successful)return;c=[].concat(b.subscription);Faye.each(c,function(a){this._f.set(a,[d,f])},this)},this)},unsubscribe:function(c,d,f){if(this._0!==this._8)return;c=[].concat(c);this._l(c);var g=this.generateId();this._4.send({channel:Faye.Channel.UNSUBSCRIBE,clientId:this._9,subscription:c,id:g},function(b){if(b.id!==g)return;if(!b.successful)return;c=[].concat(b.subscription);Faye.each(c,function(a){this._f.set(a,null)},this)},this)},publish:function(a,b){if(this._0!==this._8)return;this._l([a]);this.enqueue({channel:a,data:b,clientId:this._9});if(this._r)return;var c=this;this._r=setTimeout(function(){delete c._r;c.flush()},this.MAX_DELAY*1000)},generateId:function(a){a=a||32;return Math.floor(Math.pow(2,a)*Math.random()).toString(16)},enqueue:function(a){this._k.push(a)},flush:function(){this._4.send(this._k);this._k=[]},_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+'"';})},_v:function(a){Faye.extend(this._7,a);if(this._7.reconnect===this._p)this._9=null},_w:function(b){var c=this._f.glob(b.channel);Faye.each(c,function(a){if(!a)return;a[0].call(a[1],b.data)})}});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');}}}());
@@ -5,10 +5,10 @@ require 'rubygems'
5
5
  require 'eventmachine'
6
6
 
7
7
  module Faye
8
- VERSION = '0.1.1'
8
+ VERSION = '0.2.2'
9
9
 
10
10
  ROOT = File.expand_path(File.dirname(__FILE__))
11
- CLIENT_SCRIPT = File.join(ROOT, 'faye-min.js')
11
+ CLIENT_SCRIPT = File.join(ROOT, 'faye-client-min.js')
12
12
 
13
13
  BAYEUX_VERSION = '1.0'
14
14
  ID_LENGTH = 128
@@ -4,6 +4,10 @@ require 'json'
4
4
 
5
5
  module Faye
6
6
  class RackAdapter
7
+
8
+ # Only supported under Thin
9
+ ASYNC_RESPONSE = [-1, {}, []].freeze
10
+
7
11
  DEFAULT_ENDPOINT = '/bayeux'
8
12
 
9
13
  TYPE_JSON = {'Content-Type' => 'text/json'}
@@ -24,19 +28,20 @@ module Faye
24
28
  case request.path_info
25
29
 
26
30
  when @endpoint then
27
- message = JSON.parse(request.params['message'])
28
- jsonp = request.params['jsonp'] || JSONP_CALLBACK
29
- type = request.get? ? TYPE_SCRIPT : TYPE_JSON
30
- response = nil
31
-
32
- @server.process(message, false) do |replies|
33
- response = JSON.unparse(replies)
34
- response = "#{ jsonp }(#{ response });" if request.get?
31
+ begin
32
+ message = JSON.parse(request.params['message'])
33
+ jsonp = request.params['jsonp'] || JSONP_CALLBACK
34
+
35
+ @server.flush_connection(message) if request.get?
36
+
37
+ on_response(env, message) do |replies|
38
+ response = JSON.unparse(replies)
39
+ response = "#{ jsonp }(#{ response });" if request.get?
40
+ response
41
+ end
42
+ rescue
43
+ [400, {'Content-Type' => 'text/plain'}, 'Bad request']
35
44
  end
36
-
37
- # TODO support Thin's async responses
38
- sleep(0.1) while response.nil?
39
- [200, type, [response]]
40
45
 
41
46
  when @script then
42
47
  [200, TYPE_SCRIPT, File.new(CLIENT_SCRIPT)]
@@ -48,6 +53,33 @@ module Faye
48
53
  end
49
54
  end
50
55
 
56
+ private
57
+
58
+ def on_response(env, message, &block)
59
+ request = Rack::Request.new(env)
60
+ type = request.get? ? TYPE_SCRIPT : TYPE_JSON
61
+ callback = env['async.callback']
62
+
63
+ EM.run unless EM.reactor_running?
64
+
65
+ if callback
66
+ body = DeferredBody.new
67
+ callback.call [200, type, body]
68
+ @server.process(message, false) { |r| body.succeed block.call(r) }
69
+ return ASYNC_RESPONSE
70
+ end
71
+
72
+ response = nil
73
+ @server.process(message, false) { |r| response = block.call(r) }
74
+ sleep(0.1) while response.nil?
75
+ [200, type, [response]]
76
+ end
77
+
78
+ class DeferredBody
79
+ include EventMachine::Deferrable
80
+ alias :each :callback
81
+ end
82
+
51
83
  end
52
84
  end
53
85
 
@@ -4,7 +4,16 @@ module Faye
4
4
  @options = options
5
5
  @channels = Channel::Tree.new
6
6
  @clients = {}
7
- Thread.new { EventMachine.run } unless EventMachine.reactor_running?
7
+ end
8
+
9
+ # Notifies the server of stale connections that should be deleted
10
+ def update(message, client)
11
+ return unless message == :stale_client
12
+ destroy_client(client)
13
+ end
14
+
15
+ def client_ids
16
+ @clients.keys
8
17
  end
9
18
 
10
19
  def process(messages, local = false, &callback)
@@ -21,6 +30,34 @@ module Faye
21
30
  end
22
31
  end
23
32
 
33
+ def flush_connection(messages)
34
+ [messages].flatten.each do |message|
35
+ client = @clients[message['clientId']]
36
+ client.flush! if client
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def generate_id
43
+ id = Faye.random
44
+ id = Faye.random while @clients.has_key?(id)
45
+ connection(id).id
46
+ end
47
+
48
+ def connection(id)
49
+ return @clients[id] if @clients.has_key?(id)
50
+ client = Connection.new(id, @options)
51
+ client.add_observer(self)
52
+ @clients[id] = client
53
+ end
54
+
55
+ def destroy_client(client)
56
+ client.disconnect!
57
+ client.delete_observer(self)
58
+ @clients.delete(client.id)
59
+ end
60
+
24
61
  def handle(message, local = false, &callback)
25
62
  client_id = message['clientId']
26
63
  channel = message['channel']
@@ -196,36 +233,6 @@ module Faye
196
233
  response
197
234
  end
198
235
 
199
- # Notifies the server of stale connections that should be deleted
200
- def update(message, client)
201
- return unless message == :stale_client
202
- destroy_client(client)
203
- end
204
-
205
- def client_ids
206
- @clients.keys
207
- end
208
-
209
- private
210
-
211
- def generate_id
212
- id = Faye.random
213
- id = Faye.random while @clients.has_key?(id)
214
- connection(id).id
215
- end
216
-
217
- def connection(id)
218
- return @clients[id] if @clients.has_key?(id)
219
- client = Connection.new(id, @options)
220
- client.add_observer(self)
221
- @clients[id] = client
222
- end
223
-
224
- def destroy_client(client)
225
- client.disconnect!
226
- client.delete_observer(self)
227
- @clients.delete(client.id)
228
- end
229
236
  end
230
237
  end
231
238
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: faye
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Coglan
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-26 00:00:00 +01:00
12
+ date: 2010-02-11 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -42,6 +42,26 @@ dependencies:
42
42
  - !ruby/object:Gem::Version
43
43
  version: "0"
44
44
  version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: rubyforge
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 2.0.3
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: gemcutter
57
+ type: :development
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 0.3.0
64
+ version:
45
65
  - !ruby/object:Gem::Dependency
46
66
  name: hoe
47
67
  type: :development
@@ -50,7 +70,7 @@ dependencies:
50
70
  requirements:
51
71
  - - ">="
52
72
  - !ruby/object:Gem::Version
53
- version: 2.0.0
73
+ version: 2.5.0
54
74
  version:
55
75
  description: ""
56
76
  email:
@@ -63,6 +83,7 @@ extra_rdoc_files:
63
83
  - History.txt
64
84
  - Manifest.txt
65
85
  - README.txt
86
+ - examples/shared/public/robots.txt
66
87
  files:
67
88
  - History.txt
68
89
  - Manifest.txt
@@ -70,16 +91,21 @@ files:
70
91
  - Rakefile
71
92
  - jake.yml
72
93
  - Jakefile
73
- - client/util/class.js
74
- - client/util/event.js
75
- - client/util/json.js
76
- - client/util/uri.js
77
- - client/util/xhr.js
78
- - client/faye.js
79
- - client/transport.js
80
- - client/client.js
81
- - client/channel.js
82
- - lib/faye-min.js
94
+ - build/faye.js
95
+ - build/faye-client-min.js
96
+ - examples/README.rdoc
97
+ - examples/shared/public/index.html
98
+ - examples/shared/public/favicon.ico
99
+ - examples/shared/public/jquery.js
100
+ - examples/shared/public/robots.txt
101
+ - examples/shared/public/soapbox.js
102
+ - examples/shared/public/style.css
103
+ - examples/node/app.js
104
+ - examples/node/faye.js
105
+ - examples/node/faye-client-min.js
106
+ - examples/rack/app.rb
107
+ - examples/rack/config.ru
108
+ - lib/faye-client-min.js
83
109
  - lib/faye.rb
84
110
  - lib/faye/channel.rb
85
111
  - lib/faye/connection.rb
@@ -87,18 +113,13 @@ files:
87
113
  - lib/faye/grammar.rb
88
114
  - lib/faye/rack_adapter.rb
89
115
  - lib/faye/server.rb
90
- - examples/soapbox/README
91
- - examples/soapbox/app.rb
92
- - examples/soapbox/config.ru
93
- - examples/soapbox/public/jquery.js
94
- - examples/soapbox/public/soapbox.js
95
- - examples/soapbox/public/style.css
96
- - examples/soapbox/views/index.erb
97
116
  - test/test_channel.rb
98
117
  - test/test_grammar.rb
99
118
  - test/test_server.rb
100
119
  has_rdoc: true
101
120
  homepage: http://github.com/jcoglan/faye
121
+ licenses: []
122
+
102
123
  post_install_message:
103
124
  rdoc_options:
104
125
  - --main
@@ -120,11 +141,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
141
  requirements: []
121
142
 
122
143
  rubyforge_project: faye
123
- rubygems_version: 1.3.1
144
+ rubygems_version: 1.3.5
124
145
  signing_key:
125
- specification_version: 2
146
+ specification_version: 3
126
147
  summary: ""
127
148
  test_files:
149
+ - test/test_grammar.rb
128
150
  - test/test_server.rb
129
151
  - test/test_channel.rb
130
- - test/test_grammar.rb
@@ -1,135 +0,0 @@
1
- Faye.Channel = {
2
- HANDSHAKE: '<%= Faye::Channel::HANDSHAKE %>',
3
- CONNECT: '<%= Faye::Channel::CONNECT %>',
4
- SUBSCRIBE: '<%= Faye::Channel::SUBSCRIBE %>',
5
- UNSUBSCRIBE: '<%= Faye::Channel::UNSUBSCRIBE %>',
6
- DISCONNECT: '<%= Faye::Channel::DISCONNECT %>',
7
-
8
- META: '<%= Faye::Channel::META %>',
9
- SERVICE: '<%= Faye::Channel::SERVICE %>',
10
-
11
- isValid: function(name) {
12
- return Faye.Grammar.CHANNEL_NAME.test(name) ||
13
- Faye.Grammar.CHANNEL_PATTERN.test(name);
14
- },
15
-
16
- parse: function(name) {
17
- if (!this.isValid(name)) return null;
18
- return name.split('/').slice(1);
19
- },
20
-
21
- isMeta: function(name) {
22
- var segments = this.parse(name);
23
- return segments ? (segments[0] === this.META) : null;
24
- },
25
-
26
- isService: function(name) {
27
- var segments = this.parse(name);
28
- return segments ? (segments[0] === this.SERVICE) : null;
29
- },
30
-
31
- isSubscribable: function(name) {
32
- if (!this.isValid(name)) return null;
33
- return !this.isMeta(name) && !this.isService(name);
34
- },
35
-
36
- Tree: Faye.Class({
37
- initialize: function(value) {
38
- this._value = value;
39
- this._children = {};
40
- },
41
-
42
- eachChild: function(block, context) {
43
- Faye.each(this._children, function(key, subtree) {
44
- block.call(context, key, subtree);
45
- });
46
- },
47
-
48
- each: function(prefix, block, context) {
49
- this.eachChild(function(path, subtree) {
50
- path = prefix.concat(path);
51
- subtree.each(path, block, context);
52
- });
53
- if (this._value !== undefined) block.call(context, prefix, this._value);
54
- },
55
-
56
- map: function(block, context) {
57
- var result = [];
58
- this.each([], function(path, value) {
59
- result.push(block.call(context, path, value));
60
- });
61
- return result;
62
- },
63
-
64
- get: function(name) {
65
- var tree = this.traverse(name);
66
- return tree ? tree._value : null;
67
- },
68
-
69
- set: function(name, value) {
70
- var subtree = this.traverse(name, true);
71
- if (subtree) subtree._value = value;
72
- },
73
-
74
- traverse: function(path, createIfAbsent) {
75
- if (typeof path === 'string') path = Faye.Channel.parse(path);
76
-
77
- if (path === null) return null;
78
- if (path.length === 0) return this;
79
-
80
- var subtree = this._children[path[0]];
81
- if (!subtree && !createIfAbsent) return null;
82
- if (!subtree) subtree = this._children[path[0]] = new Faye.Channel.Tree();
83
-
84
- return subtree.traverse(path.slice(1), createIfAbsent);
85
- },
86
-
87
- glob: function(path) {
88
- if (typeof path === 'string') path = Faye.Channel.parse(path);
89
-
90
- if (path === null) return [];
91
- if (path.length === 0) return (this._value === undefined) ? [] : [this._value];
92
-
93
- var list = [];
94
-
95
- if (Faye.enumEqual(path, ['*'])) {
96
- Faye.each(this._children, function(key, subtree) {
97
- if (subtree._value !== undefined) list.push(subtree._value);
98
- });
99
- return list;
100
- }
101
-
102
- if (Faye.enumEqual(path, ['**'])) {
103
- list = this.map(function(key, value) { return value });
104
- list.pop();
105
- return list;
106
- }
107
-
108
- Faye.each(this._children, function(key, subtree) {
109
- if (key !== path[0] && key !== '*') return;
110
- var sublist = subtree.glob(path.slice(1));
111
- Faye.each(sublist, function(channel) { list.push(channel) });
112
- });
113
-
114
- if (this._children['**']) list.push(this._children['**']._value);
115
- return list;
116
- }
117
-
118
- /**
119
- Tests
120
-
121
- glob = new Faye.Channel.Tree();
122
- list = '/foo/bar /foo/boo /foo /foobar /foo/bar/boo /foobar/boo /foo/* /foo/**'.split(' ');
123
-
124
- Faye.each(list, function(c, i) {
125
- glob.set(c, i + 1);
126
- });
127
-
128
- console.log(glob.glob('/foo/*').sort()); // 1,2,7,8
129
- console.log(glob.glob('/foo/bar').sort()); // 1,7,8
130
- console.log(glob.glob('/foo/**').sort()); // 1,2,5,7,8
131
- console.log(glob.glob('/foo/bar/boo').sort()); // 5,8
132
- **/
133
- })
134
- };
135
-