rasti-web 0.0.3 → 0.0.4
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 +1 -0
- data/lib/rasti/web/channel.rb +35 -0
- data/lib/rasti/web/render.rb +14 -0
- data/lib/rasti/web/server_sent_event.rb +31 -0
- data/lib/rasti/web/stream.rb +39 -0
- data/lib/rasti/web/version.rb +1 -1
- data/lib/rasti/web.rb +5 -0
- data/spec/minitest_helper.rb +1 -0
- data/spec/render_spec.rb +38 -0
- data/spec/streaming_spec.rb +29 -0
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc7120ef16d98aaab088dc1d70dc5605cefce9bf
|
4
|
+
data.tar.gz: eba0f9c11f7df1078c299e10c108b83885eff925
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0858476701c4d950f8827374183bed0cb69bbc341cf9755b5b0282a480770bcb8a6c4a81105ae5b4f435b9035a4d8ac53f01181fa2a237243b8a12e0cdeb390
|
7
|
+
data.tar.gz: 03ea9bd24694ad5fa7e38b892d84d52e3b24bf32702133fbcef4414812eeafad52228cc8430ba77508b3fc82bdbb29b4f68c79e7e3ebd4913ac6bf0c84bddbf1
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Rasti
|
2
|
+
module Web
|
3
|
+
class Channel
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@mutex = Mutex.new
|
7
|
+
@streams = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def subscribe
|
11
|
+
Stream.new.tap do |stream|
|
12
|
+
@mutex.synchronize do
|
13
|
+
@streams << stream
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def publish(message)
|
19
|
+
@mutex.synchronize do
|
20
|
+
@streams.delete_if(&:closed?)
|
21
|
+
Rasti::Web.logger.debug(Channel) { "Broadcasting (#{@streams.count} connections) -> #{message}" } unless @streams.empty?
|
22
|
+
@streams.each do |stream|
|
23
|
+
stream.write message
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.[](id)
|
29
|
+
@channels ||= Hash.new { |h,k| h[k] = Channel.new }
|
30
|
+
@channels[id]
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/rasti/web/render.rb
CHANGED
@@ -40,6 +40,12 @@ module Rasti
|
|
40
40
|
script
|
41
41
|
end
|
42
42
|
|
43
|
+
def css(stylesheet, *args)
|
44
|
+
respond_with extract_status(args),
|
45
|
+
extract_headers(args).merge('Content-Type' => 'text/css; charset=utf-8'),
|
46
|
+
stylesheet
|
47
|
+
end
|
48
|
+
|
43
49
|
def file(filename, *args)
|
44
50
|
content_type = MIME::Types.of(filename).first.content_type
|
45
51
|
body = File.read filename
|
@@ -66,6 +72,14 @@ module Rasti
|
|
66
72
|
layout(layout_template) { view_context.render template, locals }
|
67
73
|
end
|
68
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
|
+
|
69
83
|
private
|
70
84
|
|
71
85
|
def respond_with(status, headers, body)
|
@@ -0,0 +1,31 @@
|
|
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
|
@@ -0,0 +1,39 @@
|
|
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 opened?
|
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 opened?
|
34
|
+
!closed?
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/rasti/web/version.rb
CHANGED
data/lib/rasti/web.rb
CHANGED
@@ -4,6 +4,7 @@ require 'json'
|
|
4
4
|
require 'mime-types'
|
5
5
|
require 'class_config'
|
6
6
|
require 'forwardable'
|
7
|
+
require 'logger'
|
7
8
|
|
8
9
|
require_relative 'web/route'
|
9
10
|
require_relative 'web/router'
|
@@ -14,6 +15,9 @@ require_relative 'web/view_context'
|
|
14
15
|
require_relative 'web/render'
|
15
16
|
require_relative 'web/request'
|
16
17
|
require_relative 'web/controller'
|
18
|
+
require_relative 'web/channel'
|
19
|
+
require_relative 'web/stream'
|
20
|
+
require_relative 'web/server_sent_event'
|
17
21
|
require_relative 'web/version'
|
18
22
|
|
19
23
|
module Rasti
|
@@ -26,6 +30,7 @@ module Rasti
|
|
26
30
|
attr_config :template_engines, [:erb]
|
27
31
|
attr_config :default_layout, 'layout'
|
28
32
|
attr_config :helpers, []
|
33
|
+
attr_config :logger, Logger.new(STDOUT)
|
29
34
|
|
30
35
|
after_config do |config|
|
31
36
|
config.helpers.each { |h| ViewContext.send :include, h }
|
data/spec/minitest_helper.rb
CHANGED
data/spec/render_spec.rb
CHANGED
@@ -204,6 +204,44 @@ describe Rasti::Web::Render do
|
|
204
204
|
|
205
205
|
end
|
206
206
|
|
207
|
+
describe 'CSS' do
|
208
|
+
|
209
|
+
it 'Body' do
|
210
|
+
render.css 'body{margin:0}'
|
211
|
+
|
212
|
+
response.status.must_equal 200
|
213
|
+
response['Content-Type'].must_equal 'text/css; charset=utf-8'
|
214
|
+
response.body.must_equal ['body{margin:0}']
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'Body and status' do
|
218
|
+
render.css 'body{margin:0}', 206
|
219
|
+
|
220
|
+
response.status.must_equal 206
|
221
|
+
response['Content-Type'].must_equal 'text/css; charset=utf-8'
|
222
|
+
response.body.must_equal ['body{margin:0}']
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'Body and headers' do
|
226
|
+
render.css 'body{margin:0}', 'Content-Encoding' => 'gzip'
|
227
|
+
|
228
|
+
response.status.must_equal 200
|
229
|
+
response['Content-Type'].must_equal 'text/css; charset=utf-8'
|
230
|
+
response['Content-Encoding'].must_equal 'gzip'
|
231
|
+
response.body.must_equal ['body{margin:0}']
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'Body, status and headers' do
|
235
|
+
render.css 'body{margin:0}', 206, 'Content-Encoding' => 'gzip'
|
236
|
+
|
237
|
+
response.status.must_equal 206
|
238
|
+
response['Content-Type'].must_equal 'text/css; charset=utf-8'
|
239
|
+
response['Content-Encoding'].must_equal 'gzip'
|
240
|
+
response.body.must_equal ['body{margin:0}']
|
241
|
+
end
|
242
|
+
|
243
|
+
end
|
244
|
+
|
207
245
|
describe 'File' do
|
208
246
|
|
209
247
|
let(:filename) { File.expand_path '../sample_file.zip', __FILE__ }
|
@@ -0,0 +1,29 @@
|
|
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
|
+
it 'Server sent events' do
|
10
|
+
events = []
|
11
|
+
stream = render.server_sent_events :test_channel
|
12
|
+
|
13
|
+
thread = Thread.new do
|
14
|
+
stream.each { |e| events << e }
|
15
|
+
end
|
16
|
+
|
17
|
+
3.times do |i|
|
18
|
+
data = {text: "Tick #{i}"}
|
19
|
+
event = Rasti::Web::ServerSentEvent.new data, id: i, event: 'tick'
|
20
|
+
Rasti::Web::Channel[:test_channel].publish event
|
21
|
+
end
|
22
|
+
|
23
|
+
while events.count < 3; sleep 0.0001 end
|
24
|
+
stream.close
|
25
|
+
|
26
|
+
events.must_equal 3.times.map { |i| "id: #{i}\nevent: tick\ndata: {\"text\":\"Tick #{i}\"}\n\n" }
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
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.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gabriel Naiman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -183,12 +183,15 @@ files:
|
|
183
183
|
- lib/rasti-web.rb
|
184
184
|
- lib/rasti/web.rb
|
185
185
|
- lib/rasti/web/application.rb
|
186
|
+
- lib/rasti/web/channel.rb
|
186
187
|
- lib/rasti/web/controller.rb
|
187
188
|
- lib/rasti/web/endpoint.rb
|
188
189
|
- lib/rasti/web/render.rb
|
189
190
|
- lib/rasti/web/request.rb
|
190
191
|
- lib/rasti/web/route.rb
|
191
192
|
- lib/rasti/web/router.rb
|
193
|
+
- lib/rasti/web/server_sent_event.rb
|
194
|
+
- lib/rasti/web/stream.rb
|
192
195
|
- lib/rasti/web/template.rb
|
193
196
|
- lib/rasti/web/version.rb
|
194
197
|
- lib/rasti/web/view_context.rb
|
@@ -203,6 +206,7 @@ files:
|
|
203
206
|
- spec/route_spec.rb
|
204
207
|
- spec/router_spec.rb
|
205
208
|
- spec/sample_file.zip
|
209
|
+
- spec/streaming_spec.rb
|
206
210
|
- spec/template_spec.rb
|
207
211
|
- spec/views/context_and_locals.erb
|
208
212
|
- spec/views/context_method.erb
|
@@ -230,7 +234,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
230
234
|
version: '0'
|
231
235
|
requirements: []
|
232
236
|
rubyforge_project:
|
233
|
-
rubygems_version: 2.
|
237
|
+
rubygems_version: 2.4.7
|
234
238
|
signing_key:
|
235
239
|
specification_version: 4
|
236
240
|
summary: Web blocks to build robust applications
|
@@ -245,6 +249,7 @@ test_files:
|
|
245
249
|
- spec/route_spec.rb
|
246
250
|
- spec/router_spec.rb
|
247
251
|
- spec/sample_file.zip
|
252
|
+
- spec/streaming_spec.rb
|
248
253
|
- spec/template_spec.rb
|
249
254
|
- spec/views/context_and_locals.erb
|
250
255
|
- spec/views/context_method.erb
|