em-midori 0.1.1 → 0.1.2

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: 2dcc440db5d1538e1e4530d9d6879c9a4115ee85
4
- data.tar.gz: b6912e55681783ebcd555de7b13c5d8681a213a8
3
+ metadata.gz: 6f38d205f0e4f20a31cfdec6103d2f51367dc4f8
4
+ data.tar.gz: 5edb796b384fdf26b0f2ad2e1e4c7d4ff74308b4
5
5
  SHA512:
6
- metadata.gz: 6b004b9d39d894840e6c2652dda4162d25be4be82f5532c3bedf61a189103e64b9d874312a686ccaa60469977d4f070bc4a6e09959cbcc24db3f7448ca0af648
7
- data.tar.gz: 9d4c89c1930ce59fe8590f2f26f2fda1972d768145c054803e8f0f2d8aecf840a44f52c50d026c5026cb0233ed8759ff6f443b11e9dd89043ee301a09a2fae88
6
+ metadata.gz: c1fb15aa76bac728a030b5f2989c401cddd29a279505fd51c9b52c6c74c3c00759336edcc091cc864b7f3cab060de7bbf7de3c0e77cc2019e62e4cc48cee3f15
7
+ data.tar.gz: c3dd1c67a230b4a3de6d5b7e1a41d225021728c50951d4993703c1579d2e2c18086bd5ec8ba144023acdff81c403938b4b2c3a00a5be43f2f2422461ac511fcb
data/lib/em-midori.rb CHANGED
@@ -11,6 +11,7 @@ require_relative 'em-midori/core_ext/configurable'
11
11
  require_relative 'em-midori/core_ext/string'
12
12
  require_relative 'em-midori/core_ext/promise'
13
13
  require_relative 'em-midori/core_ext/define_class'
14
+ require_relative 'em-midori/core_ext/proc'
14
15
 
15
16
  require_relative 'em-midori/version'
16
17
  require_relative 'em-midori/const'
@@ -21,6 +22,7 @@ require_relative 'em-midori/response'
21
22
  require_relative 'em-midori/api'
22
23
  require_relative 'em-midori/api_engine'
23
24
  require_relative 'em-midori/route'
25
+ require_relative 'em-midori/sandbox'
24
26
  require_relative 'em-midori/server'
25
27
  require_relative 'em-midori/websocket'
26
28
  require_relative 'em-midori/eventsource'
data/lib/em-midori/api.rb CHANGED
@@ -107,7 +107,7 @@ class Midori::API
107
107
  # puts 'Hello World'
108
108
  # end
109
109
  def eventsource(path, &block) end
110
-
110
+
111
111
  # Mount a route prefix with another API defined
112
112
  # @param [String] prefix prefix of the route String
113
113
  # @param [Class] api inherited from Midori::API
@@ -117,6 +117,10 @@ class Midori::API
117
117
  @routes[:MOUNT] << [prefix, api]
118
118
  end
119
119
 
120
+ def capture(error, &block)
121
+ Midori::Sandbox.add_rule(error, block)
122
+ end
123
+
120
124
  # Implementation of route DSL
121
125
  # @param [ String ] method HTTP method
122
126
  # @param [ String, Regexp ] path path definition
@@ -56,16 +56,16 @@ class Midori::APIEngine
56
56
  # Send 101 Switching Protocol
57
57
  connection.send_data Midori::Response.new(101, Midori::APIEngine.websocket_header(request.header['Sec-WebSocket-Key']), '')
58
58
  connection.websocket.request = request
59
- -> { clean_room.instance_exec(connection.websocket, &route.function) }.call
59
+ Midori::Sandbox.run(clean_room, route.function, connection.websocket)
60
60
  return Midori::Response.new
61
61
  elsif request.eventsource?
62
62
  connection.send_data Midori::Response.new(200, Midori::Const::EVENTSOURCE_HEADER, '')
63
- -> { clean_room.instance_exec(connection.eventsource, &route.function) }.call
63
+ Midori::Sandbox.run(clean_room, route.function, connection.eventsource)
64
64
  return Midori::Response.new
65
65
  else
66
- result = -> { clean_room.instance_exec(&route.function) }.call
67
- clean_room.body = result if result.is_a?String
68
- response = clean_room.raw_response
66
+ result = Midori::Sandbox.run(clean_room, route.function)
67
+ clean_room.body = result unless result.nil?
68
+ response = (result.is_a?Midori::Response) ? result : clean_room.raw_response
69
69
  route.middlewares.reverse_each { |middleware| response = middleware.after(request, response) }
70
70
  return response
71
71
  end
@@ -1,11 +1,11 @@
1
1
  ##
2
2
  # This class is used to be sandbox of requests processing.
3
- # @attr [Fixnum] code HTTP response code
3
+ # @attr [Fixnum] status HTTP response code
4
4
  # @attr [Hash] header HTTP response header
5
- # @attr [Object] body HTTP response body. String could is accepted by default, but could leave for further process with +Midori::Midlleware+
5
+ # @attr [Object] body HTTP response body. String could is accepted by default, but could leave for further process with +Midori::Middleware+
6
6
  # @attr [Midori::Request] request HTTP request
7
7
  class Midori::CleanRoom
8
- attr_accessor :code, :header, :body, :request
8
+ attr_accessor :status, :header, :body, :request
9
9
  # @param [Midori::Request] request HTTP request
10
10
  def initialize(request)
11
11
  @status = 200
@@ -1,5 +1,5 @@
1
1
  ##
2
- # Default configuration of Midori, extends +Midori::Configurable+
2
+ # Default configuration of Midori, extends +Configurable+
3
3
  class Midori::Configure
4
4
  extend Configurable
5
5
 
@@ -1,5 +1,5 @@
1
1
  ##
2
- # Module for store Midori Consts
2
+ # Module for store Midori Const
3
3
  module Midori::Const
4
4
  # Hash table for converting numbers to HTTP/1.1 status code line
5
5
  STATUS_CODE = {
@@ -51,14 +51,14 @@ module Midori::Const
51
51
  'Server' => "Midori/#{Midori::VERSION}"
52
52
  }
53
53
 
54
- # Default header for Evenrsource response
54
+ # Default header for EventSource response
55
55
  EVENTSOURCE_HEADER = {
56
56
  'Content-Type' => 'text-event-stream',
57
57
  'Cache-Control' => 'no-cache',
58
58
  'Connection' => 'keep-alive'
59
59
  }
60
60
 
61
- # Default header for Websocket response
61
+ # Default header for WebSocket response
62
62
  WEBSOCKET_HEADER = {
63
63
  'Upgrade' => 'websocket',
64
64
  'Connection' => 'Upgrade'
@@ -0,0 +1,8 @@
1
+ class Proc
2
+ # @note Converting {Proc} to {Lambda} may have incorrect behaviours on corner cases.
3
+ # @note See {Ruby Language Issues}[https://bugs.ruby-lang.org/issues/7314] for more details.
4
+ def to_lambda (instance = Object.new)
5
+ instance.define_singleton_method(:_, &self)
6
+ instance.method(:_).to_proc
7
+ end
8
+ end
@@ -1,8 +1,10 @@
1
1
  ##
2
- # This module store errors to be handled in Midori
2
+ # This module store errors to be handled inside Midori
3
3
  module Midori::Error
4
4
  # No route matched
5
5
  class NotFound < StandardError; end
6
+ # Internal Error
7
+ class InternalError < StandardError; end
6
8
  # Midori doesn't support continuous frame of WebSockets yet
7
9
  class ContinuousFrame < StandardError; end
8
10
  # WebSocket OpCode not defined in RFC standards
@@ -54,19 +54,19 @@ class Midori::Request
54
54
  @parsed = true
55
55
  end
56
56
 
57
- # Syntatic sugar for whether a request is parsed
57
+ # Syntactic sugar for whether a request is parsed
58
58
  # @return [Boolean] parsed or not
59
59
  def parsed?
60
60
  @parsed
61
61
  end
62
62
 
63
- # Syntatic sugar for whether a request is a websocket request
63
+ # Syntactic sugar for whether a request is a websocket request
64
64
  # @return [Boolean] websocket or not
65
65
  def websocket?
66
66
  @is_websocket
67
67
  end
68
68
 
69
- # Syntatic sugar for whether a request is an eventsource request
69
+ # Syntactic sugar for whether a request is an eventsource request
70
70
  # @return [Boolean] eventsource or not
71
71
  def eventsource?
72
72
  @is_eventsource
@@ -0,0 +1,30 @@
1
+ class Midori::Sandbox
2
+ class << self
3
+ def class_initialize
4
+ @handlers = Hash.new
5
+ @handlers[Midori::Error::InternalError] = proc {|_e| Midori::Response.new(500, {}, 'Internal Server Error')}
6
+ @handlers[Midori::Error::NotFound] = proc {|_e| Midori::Response.new(404, {}, '404 Not Found')}
7
+ end
8
+
9
+ def add_rule(class_name, block)
10
+ @handlers[class_name] = block
11
+ end
12
+
13
+ def capture(error)
14
+ if @handlers[error.class].nil?
15
+ @handlers[Midori::Error::InternalError].call(error)
16
+ else
17
+ @handlers[error.class].call(error)
18
+ end
19
+ end
20
+
21
+ def run(clean_room, function, *args)
22
+ begin
23
+ function.to_lambda(clean_room).call(*args)
24
+ rescue StandardError => e
25
+ capture(e)
26
+ end
27
+ end
28
+ end
29
+ class_initialize
30
+ end
@@ -1,5 +1,5 @@
1
1
  ##
2
- # Logics to EventMachine TCP Server, running inside +EM::Connection+
2
+ # Logic to EventMachine TCP Server, running inside +EM::Connection+
3
3
  # @attr [Midori::Request] request
4
4
  # @attr [Class] api inherited from Midori::API
5
5
  # @attr [Midori::WebSocket] websocket websocket instance
@@ -17,7 +17,7 @@ module Midori::Server
17
17
  @eventsource = Midori::EventSource.new(self)
18
18
  end
19
19
 
20
- # Logics of receiving data
20
+ # Logic of receiving data
21
21
  # @param [String] data raw data
22
22
  def receive_data(data)
23
23
  lambda do
@@ -37,17 +37,17 @@ module Midori::Server
37
37
  end.call
38
38
  end
39
39
 
40
- # Logics of receiving new request
40
+ # Logic of receiving new request
41
41
  # @param [String] data raw data
42
42
  def receive_new_request(data)
43
43
  begin
44
44
  @request.parse(data)
45
45
  @response = @api.receive(request, self)
46
46
  call_event(:open) if @request.websocket?
47
- rescue Midori::Error::NotFound => _e
48
- @response = Midori::Response.new(404, {}, '404 Not Found')
47
+ rescue Midori::Error::NotFound => e
48
+ @response = Midori::Sandbox.capture(e)
49
49
  rescue => e
50
- @response = Midori::Response.new(500, {}, 'Internal Server Error')
50
+ @response = Midori::Sandbox.capture(e)
51
51
  @logger.error e.inspect.red
52
52
  @logger.warn e.backtrace.join("\n").yellow
53
53
  end
@@ -57,7 +57,7 @@ module Midori::Server
57
57
  end
58
58
  end
59
59
 
60
- # Logics of receiving WebSocket request
60
+ # Logic of receiving WebSocket request
61
61
  # @param [StringIO] data raw data
62
62
  def websocket_request(data)
63
63
  @websocket.decode(data)
@@ -76,7 +76,9 @@ module Midori::Server
76
76
  close_connection_after_writing
77
77
  rescue Midori::Error::PingPongSizeTooLarge => e
78
78
  @logger.warn e.inspect.yellow
79
- call_event(:error) # Neglect Too large ping request
79
+ call_event(:error) # Too large ping request
80
+ send_data "\b" # Opcode 0x8
81
+ close_connection_after_writing
80
82
  rescue => e
81
83
  call_event(:error)
82
84
  @logger.error e.inspect.red
@@ -1,5 +1,5 @@
1
1
  # Midori Module
2
2
  module Midori
3
3
  # Current Version Code
4
- VERSION = '0.1.1'.freeze
4
+ VERSION = '0.1.2'.freeze
5
5
  end
@@ -14,7 +14,7 @@ class Midori::WebSocket
14
14
  end
15
15
 
16
16
  # Decode raw data send from client
17
- # @param [String] data raw data
17
+ # @param [StringIO] data raw data
18
18
  def decode(data)
19
19
  # Fin and Opcode
20
20
  byte_tmp = data.getbyte
@@ -29,7 +29,7 @@ class Midori::WebSocket
29
29
  end
30
30
 
31
31
  # Decode masked message send from client
32
- # @param [String] data raw data
32
+ # @param [StringIO] data raw data
33
33
  def decode_mask(data)
34
34
  # Mask
35
35
  byte_tmp = data.getbyte
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: em-midori
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - HeckPsi Lab
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-07 00:00:00.000000000 Z
11
+ date: 2016-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: eventmachine
@@ -69,6 +69,7 @@ files:
69
69
  - lib/em-midori/const.rb
70
70
  - lib/em-midori/core_ext/configurable.rb
71
71
  - lib/em-midori/core_ext/define_class.rb
72
+ - lib/em-midori/core_ext/proc.rb
72
73
  - lib/em-midori/core_ext/promise.rb
73
74
  - lib/em-midori/core_ext/string.rb
74
75
  - lib/em-midori/error.rb
@@ -78,6 +79,7 @@ files:
78
79
  - lib/em-midori/response.rb
79
80
  - lib/em-midori/route.rb
80
81
  - lib/em-midori/runner.rb
82
+ - lib/em-midori/sandbox.rb
81
83
  - lib/em-midori/server.rb
82
84
  - lib/em-midori/version.rb
83
85
  - lib/em-midori/websocket.rb