rasti-web 0.2.3 → 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 +4 -4
- data/.travis.yml +2 -3
- data/lib/rasti/web/render.rb +0 -8
- data/lib/rasti/web/route.rb +6 -3
- data/lib/rasti/web/version.rb +1 -1
- data/lib/rasti/web.rb +2 -5
- data/rasti-web.gemspec +1 -2
- data/spec/minitest_helper.rb +0 -4
- data/spec/route_spec.rb +48 -2
- data/spec/router_spec.rb +1 -0
- metadata +6 -25
- data/lib/rasti/web/channel.rb +0 -54
- data/lib/rasti/web/server_sent_event.rb +0 -31
- data/lib/rasti/web/stream.rb +0 -39
- data/spec/streaming_spec.rb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 50a62a6c007c11424a97fd9eb207ca0cb1641bb0
|
4
|
+
data.tar.gz: 04bf7b2fe637a40625b401227d8c1ffe61088b6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22684f3a9e873bdf5e3a30e468013ebe310d33c555e7b37068f016e765eecfbd0d89e9109d2434305ba2b90afd21e6b4fc972fd1e00e5a0967848b9da90bdb95
|
7
|
+
data.tar.gz: f8ec4a69517f0c2c8eec1d130b0b70bb3ae34ac7752cdff43da466fa49b439dd072df5ed243ff303adcce1090a9b5fa28ceefa53f6c3dd12b6f223cd3ec0fda1
|
data/.travis.yml
CHANGED
data/lib/rasti/web/render.rb
CHANGED
@@ -72,14 +72,6 @@ module Rasti
|
|
72
72
|
layout(layout_template) { view_context.render template, locals }
|
73
73
|
end
|
74
74
|
|
75
|
-
def server_sent_events(channel_id)
|
76
|
-
response.status = 200
|
77
|
-
response['Content-Type'] = 'text/event-stream'
|
78
|
-
response['Cache-Control'] = 'no-cache'
|
79
|
-
response['Connection'] = 'keep-alive'
|
80
|
-
response.body = Channel[channel_id].subscribe
|
81
|
-
end
|
82
|
-
|
83
75
|
private
|
84
76
|
|
85
77
|
def respond_with(status, headers, body)
|
data/lib/rasti/web/route.rb
CHANGED
@@ -15,8 +15,8 @@ module Rasti
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def extract_params(path)
|
18
|
-
result = @regexp.match path
|
19
|
-
result ? result.names.each_with_object(
|
18
|
+
result = @regexp.match normalize(path)
|
19
|
+
result ? result.names.each_with_object(Hash::Indifferent.new) { |v,h| h[v] = result[v] } : {}
|
20
20
|
end
|
21
21
|
|
22
22
|
def call(env)
|
@@ -26,7 +26,10 @@ module Rasti
|
|
26
26
|
private
|
27
27
|
|
28
28
|
def compile
|
29
|
-
|
29
|
+
compiled = pattern.gsub(')', '){0,1}')
|
30
|
+
.gsub('/*', '(\/(?<wildcard>.*))?')
|
31
|
+
.gsub(/:[a-z0-9_-]+/) { |var| "(?<#{var[1..-1]}>[^\/?#]+)" }
|
32
|
+
%r{^#{compiled}$}
|
30
33
|
end
|
31
34
|
|
32
35
|
def normalize(path)
|
data/lib/rasti/web/version.rb
CHANGED
data/lib/rasti/web.rb
CHANGED
@@ -7,7 +7,6 @@ require 'class_config'
|
|
7
7
|
require 'forwardable'
|
8
8
|
require 'logger'
|
9
9
|
require 'hash_ext'
|
10
|
-
require 'broadcaster'
|
11
10
|
|
12
11
|
require_relative 'web/route'
|
13
12
|
require_relative 'web/router'
|
@@ -18,13 +17,11 @@ require_relative 'web/view_context'
|
|
18
17
|
require_relative 'web/render'
|
19
18
|
require_relative 'web/request'
|
20
19
|
require_relative 'web/controller'
|
21
|
-
require_relative 'web/channel'
|
22
|
-
require_relative 'web/stream'
|
23
|
-
require_relative 'web/server_sent_event'
|
24
20
|
require_relative 'web/version'
|
25
21
|
|
26
22
|
module Rasti
|
27
23
|
module Web
|
24
|
+
|
28
25
|
ROUTE_PARAMS = 'rack.request.route_params'
|
29
26
|
|
30
27
|
extend ClassConfig
|
@@ -34,10 +31,10 @@ module Rasti
|
|
34
31
|
attr_config :default_layout, 'layout'
|
35
32
|
attr_config :helpers, []
|
36
33
|
attr_config :logger, Logger.new(STDOUT)
|
37
|
-
attr_config :channels_prefix, 'rasti-web:channels'
|
38
34
|
|
39
35
|
after_config do |config|
|
40
36
|
config.helpers.each { |h| ViewContext.send :include, h }
|
41
37
|
end
|
38
|
+
|
42
39
|
end
|
43
40
|
end
|
data/rasti-web.gemspec
CHANGED
@@ -24,7 +24,6 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_dependency 'class_config', '~> 0.0.2'
|
25
25
|
spec.add_dependency 'hash_ext', '~> 0.1'
|
26
26
|
spec.add_dependency 'content-type', '~> 0.0'
|
27
|
-
spec.add_dependency 'broadcaster', '~> 0.1'
|
28
27
|
|
29
28
|
spec.add_development_dependency 'bundler', '~> 1.12'
|
30
29
|
spec.add_development_dependency 'rake', '~> 11.0'
|
@@ -34,7 +33,7 @@ Gem::Specification.new do |spec|
|
|
34
33
|
spec.add_development_dependency 'simplecov', '~> 0.12'
|
35
34
|
spec.add_development_dependency 'coveralls', '~> 0.8'
|
36
35
|
spec.add_development_dependency 'pry-nav', '~> 0.2'
|
37
|
-
spec.add_development_dependency 'rack-test'
|
36
|
+
spec.add_development_dependency 'rack-test', '~> 0.6'
|
38
37
|
|
39
38
|
if RUBY_VERSION < '2'
|
40
39
|
spec.add_development_dependency 'term-ansicolor', '~> 1.3.0'
|
data/spec/minitest_helper.rb
CHANGED
@@ -15,8 +15,4 @@ Rasti::Web.configure do |config|
|
|
15
15
|
config.views_path = File.expand_path '../views', __FILE__
|
16
16
|
config.helpers << ContextMethodHelper
|
17
17
|
config.logger.level = Logger::ERROR
|
18
|
-
end
|
19
|
-
|
20
|
-
Broadcaster.configure do |config|
|
21
|
-
config.logger = Rasti::Web.logger
|
22
18
|
end
|
data/spec/route_spec.rb
CHANGED
@@ -4,6 +4,10 @@ describe Rasti::Web::Route do
|
|
4
4
|
|
5
5
|
ROUTES = [
|
6
6
|
'/',
|
7
|
+
'/*/wildcard/action',
|
8
|
+
'/wildcard/*/action',
|
9
|
+
'/wildcard/*/action/:id',
|
10
|
+
'/wildcard/*',
|
7
11
|
'/resource',
|
8
12
|
'/resource/:id/:action',
|
9
13
|
'/:resource(/:id(/:action))'
|
@@ -45,7 +49,7 @@ describe Rasti::Web::Route do
|
|
45
49
|
route = route_for path
|
46
50
|
|
47
51
|
route.pattern.must_equal '/resource/:id/:action'
|
48
|
-
route.extract_params(path).must_equal
|
52
|
+
route.extract_params(path).must_equal id: '123', action: 'show'
|
49
53
|
route.call({}).must_equal RESPONSE
|
50
54
|
end
|
51
55
|
|
@@ -55,7 +59,49 @@ describe Rasti::Web::Route do
|
|
55
59
|
sections = path[1..-1].split('/')
|
56
60
|
|
57
61
|
route.pattern.must_equal '/:resource(/:id(/:action))'
|
58
|
-
route.extract_params(path).must_equal
|
62
|
+
route.extract_params(path).must_equal resource: sections[0], id: sections[1], action: sections[2]
|
63
|
+
route.call({}).must_equal RESPONSE
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe 'Wildcard' do
|
68
|
+
it 'Head' do
|
69
|
+
path = '/section/sub_section/wildcard/action'
|
70
|
+
|
71
|
+
route = route_for path
|
72
|
+
|
73
|
+
route.pattern.must_equal '/*/wildcard/action'
|
74
|
+
route.extract_params(path).must_equal wildcard: 'section/sub_section'
|
75
|
+
route.call({}).must_equal RESPONSE
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'Middle' do
|
79
|
+
path = '/wildcard/section/sub_section/action'
|
80
|
+
|
81
|
+
route = route_for path
|
82
|
+
|
83
|
+
route.pattern.must_equal '/wildcard/*/action'
|
84
|
+
route.extract_params(path).must_equal wildcard: 'section/sub_section'
|
85
|
+
route.call({}).must_equal RESPONSE
|
86
|
+
end
|
87
|
+
|
88
|
+
['/wildcard', '/wildcard/123', '/wildcard/123/edit'].each do |path|
|
89
|
+
it "Tail #{path}" do
|
90
|
+
route = route_for path
|
91
|
+
|
92
|
+
route.pattern.must_equal '/wildcard/*'
|
93
|
+
route.extract_params(path).must_equal wildcard: path["/wildcard/".size..-1]
|
94
|
+
route.call({}).must_equal RESPONSE
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'Params' do
|
99
|
+
path = '/wildcard/section/sub_section/action/123'
|
100
|
+
|
101
|
+
route = route_for path
|
102
|
+
|
103
|
+
route.pattern.must_equal '/wildcard/*/action/:id'
|
104
|
+
route.extract_params(path).must_equal wildcard: 'section/sub_section', id: '123'
|
59
105
|
route.call({}).must_equal RESPONSE
|
60
106
|
end
|
61
107
|
end
|
data/spec/router_spec.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rasti-web
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gabriel Naiman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -94,20 +94,6 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0.0'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: broadcaster
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - "~>"
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0.1'
|
104
|
-
type: :runtime
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - "~>"
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0.1'
|
111
97
|
- !ruby/object:Gem::Dependency
|
112
98
|
name: bundler
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -224,16 +210,16 @@ dependencies:
|
|
224
210
|
name: rack-test
|
225
211
|
requirement: !ruby/object:Gem::Requirement
|
226
212
|
requirements:
|
227
|
-
- - "
|
213
|
+
- - "~>"
|
228
214
|
- !ruby/object:Gem::Version
|
229
|
-
version: '0'
|
215
|
+
version: '0.6'
|
230
216
|
type: :development
|
231
217
|
prerelease: false
|
232
218
|
version_requirements: !ruby/object:Gem::Requirement
|
233
219
|
requirements:
|
234
|
-
- - "
|
220
|
+
- - "~>"
|
235
221
|
- !ruby/object:Gem::Version
|
236
|
-
version: '0'
|
222
|
+
version: '0.6'
|
237
223
|
description: Web blocks to build robust applications
|
238
224
|
email:
|
239
225
|
- gabynaiman@gmail.com
|
@@ -253,15 +239,12 @@ files:
|
|
253
239
|
- lib/rasti-web.rb
|
254
240
|
- lib/rasti/web.rb
|
255
241
|
- lib/rasti/web/application.rb
|
256
|
-
- lib/rasti/web/channel.rb
|
257
242
|
- lib/rasti/web/controller.rb
|
258
243
|
- lib/rasti/web/endpoint.rb
|
259
244
|
- lib/rasti/web/render.rb
|
260
245
|
- lib/rasti/web/request.rb
|
261
246
|
- lib/rasti/web/route.rb
|
262
247
|
- lib/rasti/web/router.rb
|
263
|
-
- lib/rasti/web/server_sent_event.rb
|
264
|
-
- lib/rasti/web/stream.rb
|
265
248
|
- lib/rasti/web/template.rb
|
266
249
|
- lib/rasti/web/version.rb
|
267
250
|
- lib/rasti/web/view_context.rb
|
@@ -276,7 +259,6 @@ files:
|
|
276
259
|
- spec/route_spec.rb
|
277
260
|
- spec/router_spec.rb
|
278
261
|
- spec/sample_file.zip
|
279
|
-
- spec/streaming_spec.rb
|
280
262
|
- spec/template_spec.rb
|
281
263
|
- spec/views/context_and_locals.erb
|
282
264
|
- spec/views/context_method.erb
|
@@ -319,7 +301,6 @@ test_files:
|
|
319
301
|
- spec/route_spec.rb
|
320
302
|
- spec/router_spec.rb
|
321
303
|
- spec/sample_file.zip
|
322
|
-
- spec/streaming_spec.rb
|
323
304
|
- spec/template_spec.rb
|
324
305
|
- spec/views/context_and_locals.erb
|
325
306
|
- spec/views/context_method.erb
|
data/lib/rasti/web/channel.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
module Rasti
|
2
|
-
module Web
|
3
|
-
|
4
|
-
class Channel
|
5
|
-
|
6
|
-
attr_reader :id
|
7
|
-
|
8
|
-
def initialize(id)
|
9
|
-
@id = id
|
10
|
-
@subscriptions = {}
|
11
|
-
@mutex = Mutex.new
|
12
|
-
end
|
13
|
-
|
14
|
-
def subscribe
|
15
|
-
stream = Stream.new
|
16
|
-
|
17
|
-
subscription_id = broadcaster.subscribe id do |message|
|
18
|
-
if stream.open?
|
19
|
-
stream.write message
|
20
|
-
else
|
21
|
-
sid = mutex.synchronize { subscriptions.delete stream }
|
22
|
-
broadcaster.unsubscribe sid
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
mutex.synchronize { subscriptions[stream] = subscription_id }
|
27
|
-
|
28
|
-
stream
|
29
|
-
end
|
30
|
-
|
31
|
-
def publish(message)
|
32
|
-
broadcaster.publish id, message
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.broadcaster
|
36
|
-
@broadcaster ||= Broadcaster.new id: Web.channels_prefix, logger: Web.logger
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.[](id)
|
40
|
-
@channels ||= Hash.new { |h,k| h[k] = self.new k }
|
41
|
-
@channels[id]
|
42
|
-
end
|
43
|
-
|
44
|
-
private
|
45
|
-
|
46
|
-
attr_reader :subscriptions, :mutex
|
47
|
-
|
48
|
-
def broadcaster
|
49
|
-
self.class.broadcaster
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module Rasti
|
2
|
-
module Web
|
3
|
-
class ServerSentEvent < String
|
4
|
-
|
5
|
-
attr_reader :data, :id, :event
|
6
|
-
|
7
|
-
private
|
8
|
-
|
9
|
-
def initialize(data, options={})
|
10
|
-
@data = data
|
11
|
-
@id = options[:id]
|
12
|
-
@event = options[:event]
|
13
|
-
|
14
|
-
super serialize
|
15
|
-
end
|
16
|
-
|
17
|
-
def serialize
|
18
|
-
serialized_data = data.respond_to?(:to_json) ? data.to_json : data.to_s
|
19
|
-
|
20
|
-
message = ''
|
21
|
-
message << "id: #{id}\n" if id
|
22
|
-
message << "event: #{event}\n" if event
|
23
|
-
serialized_data.split("\n").each do |d|
|
24
|
-
message << "data: #{d}\n"
|
25
|
-
end
|
26
|
-
message << "\n"
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
data/lib/rasti/web/stream.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
module Rasti
|
2
|
-
module Web
|
3
|
-
class Stream
|
4
|
-
|
5
|
-
TIMEOUT = 0.0001
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
@queue = Queue.new
|
9
|
-
@closed = false
|
10
|
-
end
|
11
|
-
|
12
|
-
def write(message)
|
13
|
-
raise 'Closed stream' if closed?
|
14
|
-
@queue << message
|
15
|
-
end
|
16
|
-
|
17
|
-
def each
|
18
|
-
while open?
|
19
|
-
message = @queue.pop
|
20
|
-
yield message if message
|
21
|
-
sleep TIMEOUT
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def close
|
26
|
-
@closed = true
|
27
|
-
end
|
28
|
-
|
29
|
-
def closed?
|
30
|
-
@closed
|
31
|
-
end
|
32
|
-
|
33
|
-
def open?
|
34
|
-
!closed?
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
data/spec/streaming_spec.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'minitest_helper'
|
2
|
-
|
3
|
-
describe 'Straming' do
|
4
|
-
|
5
|
-
let(:request) { Rack::Request.new Hash.new }
|
6
|
-
let(:response) { Rack::Response.new }
|
7
|
-
let(:render) { Rasti::Web::Render.new request, response }
|
8
|
-
|
9
|
-
def wait_for(&block)
|
10
|
-
Timeout.timeout(3) do
|
11
|
-
while !block.call
|
12
|
-
sleep 0.0001
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'Server sent events' do
|
18
|
-
render.server_sent_events :channel_1
|
19
|
-
|
20
|
-
response.status.must_equal 200
|
21
|
-
response['Content-Type'].must_equal 'text/event-stream'
|
22
|
-
response['Cache-Control'].must_equal 'no-cache'
|
23
|
-
response['Connection'].must_equal 'keep-alive'
|
24
|
-
response.body.must_be_instance_of Rasti::Web::Stream
|
25
|
-
|
26
|
-
events = []
|
27
|
-
|
28
|
-
Thread.new do
|
29
|
-
response.body.each { |e| events << e }
|
30
|
-
end
|
31
|
-
|
32
|
-
channel_1 = Rasti::Web::Channel[:channel_1]
|
33
|
-
channel_2 = Rasti::Web::Channel[:channel_2]
|
34
|
-
|
35
|
-
3.times do |i|
|
36
|
-
data = {text: "Tick #{i}"}
|
37
|
-
event = Rasti::Web::ServerSentEvent.new data, id: i, event: 'tick'
|
38
|
-
channel_1.publish event
|
39
|
-
channel_2.publish event
|
40
|
-
end
|
41
|
-
|
42
|
-
wait_for { events.count == 3 }
|
43
|
-
|
44
|
-
response.body.close
|
45
|
-
|
46
|
-
events.must_equal 3.times.map { |i| "id: #{i}\nevent: tick\ndata: {\"text\":\"Tick #{i}\"}\n\n" }
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|