meerkat 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -5,6 +5,13 @@ Rack middleware for [Server-Sent Events (HTML5 SSE)](http://www.html5rocks.com/e
5
5
 
6
6
  Requires an [EventMachine](https://github.com/eventmachine/eventmachine#readme) backed server, like [Thin](http://code.macournoyer.com/thin/) or [Rainbows](http://rainbows.rubyforge.org/) (with the EventMachine backend only).
7
7
 
8
+ Features:
9
+ * Subscribe for single events
10
+ * Subscribe for multiple events with patterns
11
+ * Low memory and CPU usage
12
+ * Works with all proxies (unlike WebSockets)
13
+ * Allows publishing from server side as well as from the client side (with POST request)
14
+
8
15
  Supported backends:
9
16
 
10
17
  * In memory, using [EventMachine Channels](http://eventmachine.rubyforge.org/EventMachine/Channel.html), good for single server usage.
@@ -42,14 +49,24 @@ On the client:
42
49
  ```javascript
43
50
  var source = new EventSource('/stream/mychannel');
44
51
  var streamList = document.getElementById('stream');
45
- source.addEventListener('message', function(e) {
52
+ // Use #onmessage if you only listen to one topic
53
+ source.onmessage = function(e) {
46
54
  var li = document.createElement('li');
47
55
  li.innerHTML = JSON.parse(e.data);
48
56
  streamList.appendChild(li);
57
+ }
58
+ var multiSource = new EventSource('/my/event/*');
59
+ // You have to add custom event listerns when you
60
+ // listen on multiple topics
61
+ multiSource.addEventListener('/my/event/foo', function(e) {
62
+ // Do something
63
+ }, false);
64
+ multiSource.addEventListener('/my/event/bar', function(e) {
65
+ // Do something
49
66
  }, false);
50
67
  ```
51
68
 
52
- To push things:
69
+ To push things from the client:
53
70
 
54
71
  ```ruby
55
72
  Meerkat.publish "/mychannel", {:any => hash}
@@ -59,6 +76,14 @@ Meerkat.publish "/mychannel/3", any_object
59
76
 
60
77
  The published objects will be JSON serialized (with [Yajl](https://github.com/brianmario/yajl-ruby)) before sent to the backend. Deserialize it in the client.
61
78
 
79
+ From the client:
80
+
81
+ ```javascript
82
+ $.post('/stream/mychannel/2', { json: JSON.stringify(my_object) })
83
+ ```
84
+
85
+ A simple POST request, with a parameter called 'json' containing a JSON string.
86
+
62
87
  Read more about Server-Sent Events and the EventSource API on [HTML5Rocks](http://www.html5rocks.com/en/tutorials/eventsource/basics/).
63
88
 
64
89
  Examples
@@ -3,7 +3,6 @@ require_relative 'meerkat/rackadapter'
3
3
  require_relative 'meerkat/backend/inmemory'
4
4
  require_relative 'meerkat/backend/redis'
5
5
  require_relative 'meerkat/backend/pg'
6
-
7
6
  require 'yajl'
8
7
 
9
8
  module Meerkat
@@ -13,9 +12,9 @@ module Meerkat
13
12
  @backend = backend
14
13
  end
15
14
 
16
- def publish(route, message)
17
- json = Yajl::Encoder.encode message
18
- @backend.publish(route, json)
15
+ def publish(route, message, is_json = false)
16
+ json = is_json ? message : Yajl::Encoder.encode(message)
17
+ @backend.publish(route, json)
19
18
  end
20
19
 
21
20
  def subscribe(route, &callback)
@@ -12,6 +12,30 @@ module Meerkat
12
12
  end
13
13
 
14
14
  def call(env)
15
+ case env['REQUEST_METHOD']
16
+ when 'GET'
17
+ listen(env)
18
+ when 'POST'
19
+ post(env)
20
+ else
21
+ [404, {}, []]
22
+ end
23
+ end
24
+
25
+ def post(env)
26
+ req = Rack::Request.new env
27
+ data = req.params['data'] || req.params['msg'] || req.params['json']
28
+ if data
29
+ Meerkat.publish(req.path_info, data, true)
30
+ [204, {}, []]
31
+ else
32
+ [400,
33
+ {'Content-Type' => 'text/plain'},
34
+ ['Required POST parameter "data", "msg" or "json" is missing']]
35
+ end
36
+ end
37
+
38
+ def listen(env)
15
39
  body = DeferrableBody.new
16
40
 
17
41
  headers = {
@@ -1,3 +1,3 @@
1
1
  module Meerkat
2
- VERSION = "0.4.2"
2
+ VERSION = "0.4.3"
3
3
  end
@@ -7,8 +7,11 @@ require './lib/meerkat'
7
7
  describe 'Meerkat' do
8
8
  include Rack::Test::Methods
9
9
 
10
- def app
10
+ before do
11
11
  Meerkat.backend = Meerkat::Backend::InMemory.new
12
+ end
13
+
14
+ def app
12
15
  Rack::Builder.new {
13
16
  meerkat = Meerkat::RackAdapter.new do |m|
14
17
  m.keep_alive = 0.1
@@ -33,4 +36,35 @@ describe 'Meerkat' do
33
36
  get '/'
34
37
  assert_equal ":", last_response.body.split("\n")[1]
35
38
  end
39
+
40
+ it 'should publish POST data and treat it like JSON' do
41
+ mock = MiniTest::Mock.new
42
+ mock.expect(:publish, nil, ['/foo', '"bar"'])
43
+ Meerkat.backend = mock
44
+ post '/foo', :json => '"bar"'
45
+
46
+ assert_equal 204, last_response.status
47
+ assert mock.verify
48
+ end
49
+
50
+ it 'should return error 400 when there is no "json" POST parameters' do
51
+ post '/', :foo => 'bar'
52
+ assert_equal 400, last_response.status
53
+ end
54
+
55
+ it 'should return error 400 when there is no POST data' do
56
+ post '/foo'
57
+ assert_equal 400, last_response.status
58
+ end
59
+
60
+ it 'should return 404 for anything but GET and POST requests' do
61
+ delete '/foo'
62
+ assert_equal 404, last_response.status
63
+ options '/foo'
64
+ assert_equal 404, last_response.status
65
+ head '/foo'
66
+ assert_equal 404, last_response.status
67
+ put '/foo'
68
+ assert_equal 404, last_response.status
69
+ end
36
70
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meerkat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-27 00:00:00.000000000Z
12
+ date: 2011-11-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
16
- requirement: &70174238921400 !ruby/object:Gem::Requirement
16
+ requirement: &70262532917760 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70174238921400
24
+ version_requirements: *70262532917760
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rack-test
27
- requirement: &70174238920780 !ruby/object:Gem::Requirement
27
+ requirement: &70262532917300 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70174238920780
35
+ version_requirements: *70262532917300
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: thin_async
38
- requirement: &70174238920140 !ruby/object:Gem::Requirement
38
+ requirement: &70262532916880 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70174238920140
46
+ version_requirements: *70262532916880
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: thin-async-test
49
- requirement: &70174238919320 !ruby/object:Gem::Requirement
49
+ requirement: &70262532916440 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70174238919320
57
+ version_requirements: *70262532916440
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: em-minitest-spec
60
- requirement: &70174238918880 !ruby/object:Gem::Requirement
60
+ requirement: &70262532916020 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70174238918880
68
+ version_requirements: *70262532916020
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: yajl-ruby
71
- requirement: &70174238918400 !ruby/object:Gem::Requirement
71
+ requirement: &70262532931940 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *70174238918400
79
+ version_requirements: *70262532931940
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: eventmachine
82
- requirement: &70174238914700 !ruby/object:Gem::Requirement
82
+ requirement: &70262532931520 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *70174238914700
90
+ version_requirements: *70262532931520
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: em-hiredis
93
- requirement: &70174238914060 !ruby/object:Gem::Requirement
93
+ requirement: &70262532931080 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :runtime
100
100
  prerelease: false
101
- version_requirements: *70174238914060
101
+ version_requirements: *70262532931080
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: pg
104
- requirement: &70174238913360 !ruby/object:Gem::Requirement
104
+ requirement: &70262532930580 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,7 +109,7 @@ dependencies:
109
109
  version: '0'
110
110
  type: :runtime
111
111
  prerelease: false
112
- version_requirements: *70174238913360
112
+ version_requirements: *70262532930580
113
113
  description: Requires an evented Ruby dispatcher, like Thin
114
114
  email:
115
115
  - carl.hoerberg@gmail.com
@@ -151,7 +151,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
151
151
  version: '0'
152
152
  segments:
153
153
  - 0
154
- hash: 2628710167676549953
154
+ hash: -803937692324384329
155
155
  required_rubygems_version: !ruby/object:Gem::Requirement
156
156
  none: false
157
157
  requirements:
@@ -160,10 +160,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
160
  version: '0'
161
161
  segments:
162
162
  - 0
163
- hash: 2628710167676549953
163
+ hash: -803937692324384329
164
164
  requirements: []
165
165
  rubyforge_project: meerkat
166
- rubygems_version: 1.8.6
166
+ rubygems_version: 1.8.10
167
167
  signing_key:
168
168
  specification_version: 3
169
169
  summary: Rack middleware for HTML5 Server-Sent Events, with swappable backends