rasti-web 0.2.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|