sinapse 0.1.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e0830fca767543791482bb3d24747a07b2e8cd7e
4
+ data.tar.gz: e34f207abe290e1ea3f15a7f4625c011090f8e04
5
+ SHA512:
6
+ metadata.gz: 6ed6da3772bdf393658bf7de7780cfee57692847e1d6647215eaa3954d7242aba8888cf977f5f35e9959c1719474c473cf93899e4fa55406ff006c1bd727a837
7
+ data.tar.gz: 75b3ee32acbf69e8461374e8c36994ab7b88fbca86e10f7a4baf6222ee72c0fa09d579c1e10a3ec49b59a0deedabb775c026ee57ad4c16b0dd6527a75a7783ea
Binary file
@@ -0,0 +1 @@
1
+ �1v��?}��^=xŌ������a���c��8� Es��s�x��PO�>>?�l{�kl��*���ݬ 79����|�g�C�F ���h�_��J����β ۵�ó��W�"�ًѪ�|դ�8�e:)V;�]�*�� F���8�d��<�7\��7�h�!��:�5�ϰ6͍�(�B@t ��b3(�nD�"7�!���� �|A풝S�9���P듳�=2�*C�}�c (j(��~kV'8?�?��mX��`T
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 1.9.3
5
+ - rbx-2.2.3
6
+ services:
7
+ - redis-server
8
+
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ platform :rbx do
6
+ gem 'rubysl-securerandom'
7
+
8
+ group :development do
9
+ gem 'rubysl-prettyprint'
10
+ end
11
+
12
+ group :test do
13
+ gem 'rubysl-singleton' # required by rake
14
+ gem 'rubysl-base64' # required by em-http-request
15
+ gem 'rubysl-mutex_m' # required by minitest 5.2
16
+ end
17
+ end
@@ -0,0 +1,101 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sinapse (0.0.1)
5
+ activesupport (>= 3.0.0)
6
+ connection_pool
7
+ goliath (>= 1.0.3)
8
+ hiredis
9
+ msgpack (>= 0.5.0)
10
+ redis (>= 3.0.6)
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ activesupport (4.1.0)
16
+ i18n (~> 0.6, >= 0.6.9)
17
+ json (~> 1.7, >= 1.7.7)
18
+ minitest (~> 5.1)
19
+ thread_safe (~> 0.1)
20
+ tzinfo (~> 1.1)
21
+ addressable (2.3.5)
22
+ ansi (1.4.3)
23
+ async-rack (0.5.1)
24
+ rack (~> 1.1)
25
+ builder (3.2.2)
26
+ connection_pool (1.2.0)
27
+ cookiejar (0.3.0)
28
+ em-http-request (1.1.1)
29
+ addressable (>= 2.3.4)
30
+ cookiejar
31
+ em-socksify (>= 0.3)
32
+ eventmachine (>= 1.0.3)
33
+ http_parser.rb (>= 0.6.0.beta.2)
34
+ em-socksify (0.3.0)
35
+ eventmachine (>= 1.0.0.beta.4)
36
+ em-synchrony (1.0.3)
37
+ eventmachine (>= 1.0.0.beta.1)
38
+ em-websocket (0.3.8)
39
+ addressable (>= 2.1.1)
40
+ eventmachine (>= 0.12.9)
41
+ eventmachine (1.0.3)
42
+ goliath (1.0.3)
43
+ async-rack
44
+ em-synchrony (>= 1.0.0)
45
+ em-websocket (= 0.3.8)
46
+ eventmachine (>= 1.0.0.beta.4)
47
+ http_parser.rb (= 0.6.0.beta.2)
48
+ log4r
49
+ multi_json
50
+ rack (>= 1.2.2)
51
+ rack-contrib
52
+ rack-respond_to
53
+ hashie (2.0.5)
54
+ hiredis (0.4.5)
55
+ http_parser.rb (0.6.0.beta.2)
56
+ i18n (0.6.9)
57
+ json (1.8.1)
58
+ log4r (1.1.10)
59
+ minitest (5.2.0)
60
+ minitest-reporters (1.0.0)
61
+ ansi
62
+ builder
63
+ minitest (>= 5.0)
64
+ powerbar
65
+ msgpack (0.5.8)
66
+ multi_json (1.10.0)
67
+ powerbar (1.0.11)
68
+ ansi (~> 1.4.0)
69
+ hashie (>= 1.1.0)
70
+ rack (1.5.2)
71
+ rack-accept-media-types (0.9)
72
+ rack-contrib (1.1.0)
73
+ rack (>= 0.9.1)
74
+ rack-respond_to (0.9.8)
75
+ rack-accept-media-types (>= 0.6)
76
+ rake (10.1.1)
77
+ redis (3.0.7)
78
+ rubysl-base64 (2.0.0)
79
+ rubysl-mutex_m (2.0.0)
80
+ rubysl-prettyprint (2.0.2)
81
+ rubysl-securerandom (2.0.0)
82
+ rubysl-singleton (2.0.0)
83
+ thread_safe (0.3.3)
84
+ tzinfo (1.1.0)
85
+ thread_safe (~> 0.1)
86
+
87
+ PLATFORMS
88
+ ruby
89
+
90
+ DEPENDENCIES
91
+ bundler
92
+ em-http-request
93
+ minitest (>= 5.2.0)
94
+ minitest-reporters
95
+ rake
96
+ rubysl-base64
97
+ rubysl-mutex_m
98
+ rubysl-prettyprint
99
+ rubysl-securerandom
100
+ rubysl-singleton
101
+ sinapse!
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Julien Portalier
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,173 @@
1
+ # Sinapse
2
+
3
+ EventSource service for pushing messages written in Ruby.
4
+
5
+ Pushing messages to the browser or any other kind or client should be as easy as
6
+ posting from a browser. The technology is there with the PUB/SUB solution
7
+ offered by Redis and the simple server push protocol allowed by EventSource
8
+ (Server-Sent Events) over regular HTTP.
9
+
10
+ Sinapse is a push service running in an event-loop (thanks to Goliath and
11
+ EventMachine) and takes care of pushing all your events, and to deliver them to
12
+ whoever is allowed to receive them.
13
+
14
+
15
+ ## How it works
16
+
17
+ A user connects to the Sinapse server using a token. That token will be
18
+ associated to a list of channels that the user is authorized to listen to. That
19
+ list of channels can be updated at any time and will be applied live to existing
20
+ connection, so users will only ever receive what they are allowed to receive.
21
+
22
+ This is different from [Faye](http://faye.jcoglan.com) for example, which is
23
+ a PUB/SUB solution to have clients subscribe and publish to whatever channels
24
+ they want. Sinapse is a push service to notify clients about changes that
25
+ happened on the backend, and the list of authorized channels is thus kept on
26
+ the server.
27
+
28
+
29
+ ## Features
30
+
31
+ Sinapse is still a work in progress, and the API subject to changes, but it
32
+ already features:
33
+
34
+ - A solid architecture (Goliath + EventMachine + Redis).
35
+ - EventSource (Server-Sent Events) server with support for CORS requests,
36
+ authentication and a live updating list of channels.
37
+ - Keep EventSource connection alive by sending comments are regular intervals.
38
+ - Ruby library to manipulate user channels, authentication and to publish
39
+ messages.
40
+
41
+ TODO:
42
+
43
+ - Support [Yaffle EventSource polyfill](https://github.com/Yaffle/EventSource)
44
+ (for Internet Explorer support)
45
+ - Support for Web Sockets alongside EventSource (for native IE10+ support)
46
+ - Retain messages with some expiry to avoid missing messages because of
47
+ network connection problems.
48
+
49
+
50
+ ## Requirements
51
+
52
+ Sinapse is compatible and actively tested with Ruby 1.9.3+ and Rubinius 2.2+. It
53
+ requires a Redis 2.2+ server instance. Sinapse should be compatible with Ubuntu
54
+ 12.04 LTS out of the box. It may be compatible with older versions of Ruby,
55
+ Rubinius or Redis but this isn't supported.
56
+
57
+ Sinapse comes with a Ruby library, but it can be used from other languages,
58
+ because all the communication to the Sinapse server happens through Redis. The
59
+ protocol hasn't been formalized yet and you will have to check the ruby
60
+ implementation and test suite to understand it.
61
+
62
+
63
+ ## Usage
64
+
65
+ Declare sinapse in your Gemfile and run `bundle`:
66
+
67
+ ```ruby
68
+ gem "sinapse", github: "ysbaddaden/sinapse"
69
+ ```
70
+
71
+ You may now start the server with `bundle exec sinapse` or generate a binstub
72
+ with `bundle binstubs sinapse` then start the server with `bin/sinapse`.
73
+
74
+ Once started the server will be available on http://0.0.0.0:9000/ by default.
75
+ It can be configured to run on a UNIX socket or a specific host and port. Run
76
+ `sinapse --help` or read the Goliath documentation for more information.
77
+
78
+ ### Configuration
79
+
80
+ The Sinapse server may be configured using environment variables:
81
+
82
+ - `SINAPSE_CORS_ORIGIN` — restrict origins for CORS browser requests (defaults to `*`).
83
+ - `SINAPSE_KEEP_ALIVE` — send a comment every n seconds to keep the connection alive (defaults to `15`).
84
+ - `SINAPSE_RETRY` — EventSource retry parameter (defaults to `5`).
85
+ - `SINAPSE_CHANNEL_EVENT` — set the channel name as the event type to sent messages.
86
+
87
+ Sinapse (both the client and the server) will connect to the Redis instance
88
+ defined in the `REDIS_URL` environment variable and fallback to the default
89
+ `redis://localhost:6379/0`.
90
+
91
+ ### Authenticate
92
+
93
+ Include `Sinapse` into the subjects that will authenticate to the Sinapse
94
+ server. The example below uses ActiveRecord but Sinapse should work with any
95
+ Ruby class, as long as it responds to `#to_param`.
96
+
97
+ ```ruby
98
+ class User < ActiveRecord::Base
99
+ include Sinapse
100
+ end
101
+ ```
102
+
103
+ Once your subjects are defined, you must generate tokens for the subjects, then
104
+ declare a list of channels they are authorized to access. You are responsible
105
+ for generating and replacing the token when your application requires it. For
106
+ example you may create the token when creating the user:
107
+
108
+ ```ruby
109
+ class User < ActiveRecord::Base
110
+ include Sinapse
111
+ end
112
+
113
+ # create the token and initialize channels
114
+ user = User.create(attributes)
115
+ token = user.sinapse.auth.generate
116
+
117
+ # destroy the token and the user channels
118
+ sinapse.auth.clear
119
+ ```
120
+
121
+ You may now connect to `http://localhost:9000/?access_token=<token>` but it
122
+ will return a `401 Unauthorized` because the connected subject doesn't have any
123
+ channel to listen to.
124
+
125
+ A 401 Unauthorized HTTP status will be returned whenever an `access_token` is
126
+ invalid or the list of channels is empty. The connection may also be closed
127
+ immediately whenever the list of channels gets emptied.
128
+
129
+ ### Channels
130
+
131
+ You may now add and remove the channels that a user may be notified of at any
132
+ time. Usually a channel will be a class instance. Include `Sinapse::Publishable`
133
+ into the classes that may publish events, add them to the authorized channels of
134
+ a user, then publish your messages through the class:
135
+
136
+ ```ruby
137
+ class Room < ActiveRecord::Base
138
+ include Sinapse::Publishable
139
+ end
140
+
141
+ # add the channel to a user's channel list
142
+ room = Room.find(params[:id])
143
+ user.sinapse.add_channel(room)
144
+
145
+ # publish a message (the user will receive it)
146
+ room.publish(room.to_json)
147
+
148
+ # remove the channel
149
+ user.sinapse.remove_channel(room)
150
+
151
+ # publish another message (the user won't receive it)
152
+ room.publish(room.to_json)
153
+ ```
154
+
155
+
156
+ ## Example
157
+
158
+ Please see the [example](https://github.com/ysbaddaden/sinapse/tree/master/example)
159
+ for up to date working code. To try it start the Sinapse server with `bin/sinapse`
160
+ then the example rack application. Open http://localhost:3000 in different
161
+ browsers, and start a chat!
162
+
163
+
164
+ ## Author
165
+
166
+ - Julien Portalier
167
+
168
+
169
+ ## License
170
+
171
+ Distributed under the MIT License.
172
+ See [LICENSE](LICENSE.m://github.com/ysbaddaden/sinapse/blob/master/LICENSE).
173
+
@@ -0,0 +1,11 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ task :default => :test
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << 'test'
8
+ t.pattern = 'test/**/*_test.rb'
9
+ t.verbose = true
10
+ end
11
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,10 @@
1
+ #! /usr/bin/env ruby
2
+ $:.unshift File.expand_path("../../lib", File.realpath(__FILE__))
3
+
4
+ RACK_ENV ||= ENV['RACK_ENV'] ||= 'development'
5
+
6
+ require 'bundler/setup'
7
+ Bundler.require(:default, RACK_ENV)
8
+
9
+ require 'sinapse/server'
10
+
@@ -0,0 +1,21 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDeDCCAmCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBBMQ8wDQYDVQQDDAZqdWxp
3
+ ZW4xGTAXBgoJkiaJk/IsZAEZFglwb3J0YWxpZXIxEzARBgoJkiaJk/IsZAEZFgNj
4
+ b20wHhcNMTQwMTE0MjIzMTQ4WhcNMTUwMTE0MjIzMTQ4WjBBMQ8wDQYDVQQDDAZq
5
+ dWxpZW4xGTAXBgoJkiaJk/IsZAEZFglwb3J0YWxpZXIxEzARBgoJkiaJk/IsZAEZ
6
+ FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDpxWuWRJXEz2+p
7
+ 2EW4NOPzkKloRLWoj+WQnqhQKT46GbH3ToDId8AMELTDIKpTQFiG2ty6D7S4IBFv
8
+ 7ceFKNk/EJc17mSYE1DzrtItor2/eeGC1zeNfvLjyDtyHKyKUZ891C1D0so5coUx
9
+ 2YbDW5npFkJkPaA5GneH7DFaCoIFLrD7ekbzaZAjlH+EH2fhd1XLhSsPEIiE+OnD
10
+ ilWnsPoRJAZwQOiVAtvh7xuc+29uSNndIIm2rU00SxbJnzsAq9ZddwPpMU/UcQpD
11
+ 4gCBCaNGzrLz4+upQdYEOuggM7rR3P934qfhIwb+aRGglqdNunmUrdCuhsGXrxq2
12
+ FvqwDvFZAgMBAAGjezB5MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
13
+ BBQoESDCnNz3LmbpUzOrGeXOpk9sqjAfBgNVHREEGDAWgRRqdWxpZW5AcG9ydGFs
14
+ aWVyLmNvbTAfBgNVHRIEGDAWgRRqdWxpZW5AcG9ydGFsaWVyLmNvbTANBgkqhkiG
15
+ 9w0BAQUFAAOCAQEAML4w0F/VF0gi5JqMqYSO05TakAauG8jQX0hov5H8M0Xhl79G
16
+ BdUllH0QEw0cP6J2g46zAk0FGHIGthx0OKKi5YMYTs/KPqOVIAcJslt2sGIC1Ukm
17
+ wpOWIg1XMe68+JVTktBKcBFAvc0pLtty1TgdSd2wr7KQgfmBU9I8G6AoPYhJOhkG
18
+ SHTTSX3ms2/XePuSnyOfir/AQC7U0NalnKLNdwY9gkEdNwiTf5Ga/lZVDQ607bow
19
+ KVqCN//9bevjMk5OiMi9X3Wu/GtVWDwC6OTWFWKd54KgbuWlakO8LC1SMmStnCIF
20
+ W4qpyMWMZMcB4ZN/0mUVzY5xwrislBtsmQVUSw==
21
+ -----END CERTIFICATE-----
@@ -0,0 +1,3 @@
1
+ Rainbows! do
2
+ use :EventMachine
3
+ end
@@ -0,0 +1,22 @@
1
+ # http://en.wikibooks.org/wiki/Ruby_Programming/RubyGems#How_to_install_different_versions_of_gems_depending_on_which_version_of_ruby_the_installee_is_using
2
+ require 'rubygems'
3
+ require 'rubygems/command.rb'
4
+ require 'rubygems/dependency_installer.rb'
5
+
6
+ begin
7
+ Gem::Command.build_args = ARGV
8
+ rescue NoMethodError
9
+ end
10
+
11
+ inst = Gem::DependencyInstaller.new
12
+
13
+ begin
14
+ if RUBY_ENGINE == "rbx"
15
+ inst.install "rubysl-securerandom"
16
+ #inst.install "rubysl-base64"
17
+ end
18
+ rescue
19
+ exit 1
20
+ end
21
+
22
+ exit 0
@@ -0,0 +1,42 @@
1
+ require 'sinapse/version'
2
+ require 'sinapse/authentication'
3
+ require 'sinapse/channels'
4
+ require 'sinapse/publishable'
5
+ require 'connection_pool'
6
+ require 'redis'
7
+ require 'hiredis'
8
+
9
+ module Sinapse
10
+ def sinapse
11
+ @sinapse ||= Sinapse::Channels.new(self)
12
+ end
13
+
14
+ class << self
15
+ def redis(&block)
16
+ raise ArgumentError, "requires a block" unless block
17
+ @redis ||= ConnectionPool.new(pool_options) { Redis.new(url: config[:url]) }
18
+ @redis.with(&block)
19
+ end
20
+
21
+ def redis=(redis)
22
+ raise ArgumentError, "requires a ConnectionPool" unless redis.kind_of?(ConnectionPool)
23
+ @redis = redis
24
+ end
25
+
26
+ def config
27
+ @config ||= {
28
+ size: 5,
29
+ timeout: 5,
30
+ url: ENV['REDIS_URL'] || 'redis://localhost:6379/0'
31
+ }
32
+ end
33
+
34
+ def config=(options)
35
+ @config = config.merge(options.symbolize_keys)
36
+ end
37
+
38
+ def pool_options
39
+ @pool_options ||= { size: config[:size], timeout: config[:timeout] }
40
+ end
41
+ end
42
+ end