roda-message_bus 1.0.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.
- checksums.yaml +7 -0
- data/CHANGELOG +3 -0
- data/MIT-LICENSE +18 -0
- data/README.rdoc +73 -0
- data/Rakefile +36 -0
- data/lib/roda/plugins/message_bus.rb +78 -0
- data/spec/roda-message_bus_spec.rb +49 -0
- metadata +104 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5732e8b05b673858703a5f5d9b7b11c84b926895
|
4
|
+
data.tar.gz: d7d639e4d26bc51d359850483a393530a95a3a58
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 773e562b49b214ac1453913189a73318600726b2bd4097d2d8bb5a4fbe6d90881f46f496f22284a028a8449d773b8b9bbf14eba7a745221443365a7a9629cd1b
|
7
|
+
data.tar.gz: befafc0678b136fd2d75e9e2ff282ca12434fac937abe28df4715d7db8955da750e37ea305dde694051d4275d7f1513f359887f252d93e3d18d5b8b331c1e9ff
|
data/CHANGELOG
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2016 Jeremy Evans
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to
|
5
|
+
deal in the Software without restriction, including without limitation the
|
6
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
7
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
16
|
+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
= roda-message_bus
|
2
|
+
|
3
|
+
roda-message_bus integrates message_bus into the roda web toolkit,
|
4
|
+
allowing you to call message_bus only for specific paths, after
|
5
|
+
any access control checks have been made.
|
6
|
+
|
7
|
+
= Installation
|
8
|
+
|
9
|
+
gem install roda-message_bus
|
10
|
+
|
11
|
+
= Source Code
|
12
|
+
|
13
|
+
Source code is available on GitHub at
|
14
|
+
https://github.com/jeremyevans/roda-message_bus
|
15
|
+
|
16
|
+
= Usage
|
17
|
+
|
18
|
+
roda-message_bus is a roda plugin, so you need to load it into your roda
|
19
|
+
application similar to other plugins:
|
20
|
+
|
21
|
+
class App < Roda
|
22
|
+
plugin :message_bus
|
23
|
+
end
|
24
|
+
|
25
|
+
In your routing block, you can use +r.message_bus+ to pass the routing
|
26
|
+
to message bus. Generally you'll want to do this after making any
|
27
|
+
access control checks:
|
28
|
+
|
29
|
+
App.route do |r|
|
30
|
+
r.on "room/:id" do |room_id|
|
31
|
+
room_id = room_id.to_i
|
32
|
+
raise unless current_user.has_access?(room_id)
|
33
|
+
|
34
|
+
# Allows "/room/#{room_id}" channel by default
|
35
|
+
r.message_bus
|
36
|
+
|
37
|
+
view(:room)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
Routing will halt in +r.message_bus+ if the request is a message_bus
|
42
|
+
request. If the request is not a message_bus request, execution will
|
43
|
+
continue without yielding.
|
44
|
+
|
45
|
+
If you want to, you can force a specific message_bus channel (or channels
|
46
|
+
by passing an array) when calling r.message_bus:
|
47
|
+
|
48
|
+
# Override channel to use (can also provide array of channels)
|
49
|
+
r.message_bus("/room/#{room_id}/enters")
|
50
|
+
|
51
|
+
If you pass a block to +r.message_bus+, it will be yielded to only
|
52
|
+
if this is a message_bus request.
|
53
|
+
|
54
|
+
r.message_bus do
|
55
|
+
# executed right before passing control to message_bus
|
56
|
+
end
|
57
|
+
|
58
|
+
For roda-message_bus to work, in your MessageBus javascript code, you must
|
59
|
+
set the +baseUrl+ to match the routing tree branch where you are calling
|
60
|
+
+r.message_bus+:
|
61
|
+
|
62
|
+
<script type="text/javascript" src="/message-bus.js"></script>
|
63
|
+
<script type="text/javascript">
|
64
|
+
MessageBus.baseUrl = "<%= request.path_info %>/";
|
65
|
+
</script>
|
66
|
+
|
67
|
+
= License
|
68
|
+
|
69
|
+
MIT
|
70
|
+
|
71
|
+
= Author
|
72
|
+
|
73
|
+
Jeremy Evans <code@jeremyevans.net>
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "rake/clean"
|
3
|
+
|
4
|
+
CLEAN.include ["roda-message_bus-*.gem", "rdoc", "coverage"]
|
5
|
+
|
6
|
+
desc "Build thamble gem"
|
7
|
+
task :package=>[:clean] do |p|
|
8
|
+
sh %{#{FileUtils::RUBY} -S gem build roda-message_bus.gemspec}
|
9
|
+
end
|
10
|
+
|
11
|
+
### Specs
|
12
|
+
|
13
|
+
desc "Run specs"
|
14
|
+
task :spec do
|
15
|
+
sh "#{FileUtils::RUBY} -rubygems -I lib spec/roda-message_bus_spec.rb"
|
16
|
+
end
|
17
|
+
|
18
|
+
task :default => :spec
|
19
|
+
|
20
|
+
### RDoc
|
21
|
+
|
22
|
+
RDOC_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--main', 'README.rdoc', '--title', 'roda-message_bus: MessageBus integration for Roda']
|
23
|
+
|
24
|
+
begin
|
25
|
+
gem 'hanna-nouveau'
|
26
|
+
RDOC_OPTS.concat(['-f', 'hanna'])
|
27
|
+
rescue Gem::LoadError
|
28
|
+
end
|
29
|
+
|
30
|
+
require "rdoc/task"
|
31
|
+
|
32
|
+
RDoc::Task.new do |rdoc|
|
33
|
+
rdoc.rdoc_dir = "rdoc"
|
34
|
+
rdoc.options += RDOC_OPTS
|
35
|
+
rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/**/*.rb"
|
36
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
require 'message_bus/rack/middleware'
|
4
|
+
|
5
|
+
class Roda
|
6
|
+
module RodaPlugins
|
7
|
+
# The message_bus plugin allows for integrating the message_bus library into
|
8
|
+
# Roda's routing tree. By default, MessageBus provides a Rack middlware to
|
9
|
+
# work with any rack framework. However, that doesn't work well if you are
|
10
|
+
# integrating access control into your routing tree.
|
11
|
+
#
|
12
|
+
# With the message_bus plugin, you can specify exactly where to pass control
|
13
|
+
# to message_bus, which can be done after access controls have been checked.
|
14
|
+
# Additionally, this allows to control which message_bus channels are allowed
|
15
|
+
# for which requests, further enhancing security.
|
16
|
+
#
|
17
|
+
# It is still possible to use message_bus's user/group/site filtering when
|
18
|
+
# using this support to filter allowed channels.
|
19
|
+
#
|
20
|
+
# # Use default MessageBus
|
21
|
+
# plugin :message_bus
|
22
|
+
#
|
23
|
+
# # Use specific MessageBus implementation
|
24
|
+
# plugin :message_bus, :message_bus=>MessageBus::Instance.new
|
25
|
+
#
|
26
|
+
# route do |r|
|
27
|
+
# r.on "room/:id" do |room_id|
|
28
|
+
# room_id = room_id.to_i
|
29
|
+
# raise unless current_user.has_access?(room_id)
|
30
|
+
#
|
31
|
+
# # Uses "/room/#{room_id}" channel by default
|
32
|
+
# r.message_bus
|
33
|
+
#
|
34
|
+
# # Override channel to use (can also provide array of channels)
|
35
|
+
# r.message_bus("/room/#{room_id}/enters")
|
36
|
+
#
|
37
|
+
# # In addition to subscribing to channels,
|
38
|
+
# # in Javascript on this page, set:
|
39
|
+
# #
|
40
|
+
# # MessageBus.baseUrl = "/room/<%= room_id %>/"
|
41
|
+
# view('room')
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
module MessageBus
|
45
|
+
APP = proc{[404, {"Content-Type" => "text/html"}, ["Not Found"]]}
|
46
|
+
|
47
|
+
def self.configure(app, config={})
|
48
|
+
app.opts[:message_bus_app] = ::MessageBus::Rack::Middleware.new(APP, config)
|
49
|
+
end
|
50
|
+
|
51
|
+
module ClassMethods
|
52
|
+
def message_bus_app
|
53
|
+
opts[:message_bus_app]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
module RequestMethods
|
58
|
+
def message_bus(channels=nil)
|
59
|
+
if remaining_path =~ /\A\/message-bus\//
|
60
|
+
chans = env['message_bus.channels'] = {}
|
61
|
+
post = self.POST
|
62
|
+
channels ||= script_name + path_info.chomp(remaining_path)
|
63
|
+
Array(channels).each do |channel|
|
64
|
+
if val = post[channel]
|
65
|
+
chans[channel] = val
|
66
|
+
end
|
67
|
+
end
|
68
|
+
env['message_bus.seq'] = post['__seq']
|
69
|
+
yield if block_given?
|
70
|
+
run roda_class.message_bus_app
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
register_plugin(:message_bus, MessageBus)
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'roda'
|
2
|
+
require 'message_bus'
|
3
|
+
require 'json'
|
4
|
+
require 'minitest/autorun'
|
5
|
+
|
6
|
+
MessageBus.configure(:backend => :memory)
|
7
|
+
|
8
|
+
describe 'roda message_bus plugin' do
|
9
|
+
def req(path, input={}, env={})
|
10
|
+
env = {"PATH_INFO"=>path, "REQUEST_METHOD" => "GET", "SCRIPT_NAME" => "", 'rack.input'=>true, 'rack.request.form_input'=>true, 'rack.request.form_hash'=>input}.merge(env)
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
|
14
|
+
def body(path, input={}, env={})
|
15
|
+
s = String.new
|
16
|
+
b = req(path, input, env)[2]
|
17
|
+
b.each{|x| s << x}
|
18
|
+
b.close if b.respond_to?(:close)
|
19
|
+
s
|
20
|
+
end
|
21
|
+
|
22
|
+
def json_body(path, input={}, env={})
|
23
|
+
JSON.parse(body(path, input, env))
|
24
|
+
end
|
25
|
+
|
26
|
+
before do
|
27
|
+
@app = Class.new(Roda)
|
28
|
+
@app.plugin :message_bus
|
29
|
+
@app
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should handle message bus under a branch" do
|
33
|
+
@app.route do |r|
|
34
|
+
r.on "foo" do
|
35
|
+
r.message_bus
|
36
|
+
'bar'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
body('/foo').must_equal 'bar'
|
41
|
+
json_body('/foo/message-bus/1/poll', '/foo'=>'0', '__seq'=>1).must_equal []
|
42
|
+
MessageBus.publish '/foo', 'baz'
|
43
|
+
json_body('/foo/message-bus/1/poll', '/foo'=>'0', '__seq'=>1).must_equal [{"global_id"=>1, "message_id"=>1, "channel"=>"/foo", "data"=>"baz"}]
|
44
|
+
MessageBus.publish '/foo', 'baz1'
|
45
|
+
json_body('/foo/message-bus/1/poll', '/foo'=>'0', '__seq'=>1).must_equal [{"global_id"=>1, "message_id"=>1, "channel"=>"/foo", "data"=>"baz"}, {"global_id"=>2, "message_id"=>2, "channel"=>"/foo", "data"=>"baz1"}]
|
46
|
+
json_body('/foo/message-bus/1/poll', '/foo'=>'1', '__seq'=>1).must_equal [{"global_id"=>2, "message_id"=>2, "channel"=>"/foo", "data"=>"baz1"}]
|
47
|
+
json_body('/foo/message-bus/1/poll', '/foo'=>'1').must_equal [{"global_id"=>2, "message_id"=>2, "channel"=>"/foo", "data"=>"baz1"}]
|
48
|
+
end
|
49
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: roda-message_bus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jeremy Evans
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-06-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: message_bus
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: roda
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 2.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: |
|
56
|
+
roda-message_bus integrates message_bus into the roda web toolkit,
|
57
|
+
allowing you to call message_bus only for specific paths, after
|
58
|
+
any access control checks have been made.
|
59
|
+
email: code@jeremyevans.net
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files:
|
63
|
+
- README.rdoc
|
64
|
+
- CHANGELOG
|
65
|
+
- MIT-LICENSE
|
66
|
+
files:
|
67
|
+
- CHANGELOG
|
68
|
+
- MIT-LICENSE
|
69
|
+
- README.rdoc
|
70
|
+
- Rakefile
|
71
|
+
- lib/roda/plugins/message_bus.rb
|
72
|
+
- spec/roda-message_bus_spec.rb
|
73
|
+
homepage: https://github.com/jeremyevans/roda-message_bus
|
74
|
+
licenses:
|
75
|
+
- MIT
|
76
|
+
metadata: {}
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options:
|
79
|
+
- "--quiet"
|
80
|
+
- "--line-numbers"
|
81
|
+
- "--inline-source"
|
82
|
+
- "--title"
|
83
|
+
- 'roda-message_bus: MessageBus integration for Roda'
|
84
|
+
- "--main"
|
85
|
+
- README.rdoc
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 2.5.1
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: MessageBus integration for Roda
|
104
|
+
test_files: []
|