rasti-web 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2b2ed7458b25215ed07dd7355f1a9dc43ce98d16
4
- data.tar.gz: df11d78ed700d06e98a565ac6671f90aeb8208ed
3
+ metadata.gz: fc7120ef16d98aaab088dc1d70dc5605cefce9bf
4
+ data.tar.gz: eba0f9c11f7df1078c299e10c108b83885eff925
5
5
  SHA512:
6
- metadata.gz: 30e33136ea36d5edcd6d2179fd08c03368e218bf42fba6001d18b579fa7b7ffcbb9a40a823a12cba311994232a4472156d62cb738716438e5d48b664121aa9b6
7
- data.tar.gz: 063a8972aa3439a801ade3ff9843f4e247622528d36a8fb477737a73e655e4b5f7f58acd817b4a63230e94501e5c76b5182e1f584e46348e91662ae3f570e9a2
6
+ metadata.gz: e0858476701c4d950f8827374183bed0cb69bbc341cf9755b5b0282a480770bcb8a6c4a81105ae5b4f435b9035a4d8ac53f01181fa2a237243b8a12e0cdeb390
7
+ data.tar.gz: 03ea9bd24694ad5fa7e38b892d84d52e3b24bf32702133fbcef4414812eeafad52228cc8430ba77508b3fc82bdbb29b4f68c79e7e3ebd4913ac6bf0c84bddbf1
data/.travis.yml CHANGED
@@ -3,4 +3,5 @@ rvm:
3
3
  - 1.9.3
4
4
  - 2.0
5
5
  - 2.1
6
+ - 2.2
6
7
  - jruby
@@ -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
@@ -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
@@ -1,5 +1,5 @@
1
1
  module Rasti
2
2
  module Web
3
- VERSION = '0.0.3'
3
+ VERSION = '0.0.4'
4
4
  end
5
5
  end
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 }
@@ -20,4 +20,5 @@ end
20
20
  Rasti::Web.configure do |config|
21
21
  config.views_path = File.expand_path '../views', __FILE__
22
22
  config.helpers << ContextMethodHelper
23
+ config.logger.level = Logger::ERROR
23
24
  end
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.3
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-03-03 00:00:00.000000000 Z
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.2.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