em-midori 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b6d10050423b7536832c5ef0b7d94ead6bb713a8
4
- data.tar.gz: 949d87027c3feaece3ce05637b91569f37056978
3
+ metadata.gz: 2dcc440db5d1538e1e4530d9d6879c9a4115ee85
4
+ data.tar.gz: b6912e55681783ebcd555de7b13c5d8681a213a8
5
5
  SHA512:
6
- metadata.gz: 69ee80d129f50421830b10c57dc3712211892d9cb5e047422e7b90e7b8bf2eb2bb01fb44b03c0d1d7b6424e1843a8861be7fa040d383b73dffa9cb22ca7bce5d
7
- data.tar.gz: 1b97321457676354063864beb257e0b8ce43e5e873beb34b1dd9a08e6db0e00471ae3b99dc440071f3c561e984a608b215b0ad41f02fae2d6b4ea0d0c8dfeffb
6
+ metadata.gz: 6b004b9d39d894840e6c2652dda4162d25be4be82f5532c3bedf61a189103e64b9d874312a686ccaa60469977d4f070bc4a6e09959cbcc24db3f7448ca0af648
7
+ data.tar.gz: 9d4c89c1930ce59fe8590f2f26f2fda1972d768145c054803e8f0f2d8aecf840a44f52c50d026c5026cb0233ed8759ff6f443b11e9dd89043ee301a09a2fae88
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at dsh0416@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
@@ -4,19 +4,22 @@ require 'eventmachine'
4
4
  require 'fiber'
5
5
  require 'logger'
6
6
  require 'http/parser'
7
+ require 'mustermann'
7
8
  require 'socket'
8
9
 
9
- require_relative 'em-midori/version'
10
10
  require_relative 'em-midori/core_ext/configurable'
11
- require_relative 'em-midori/string'
12
- require_relative 'em-midori/promise'
11
+ require_relative 'em-midori/core_ext/string'
12
+ require_relative 'em-midori/core_ext/promise'
13
+ require_relative 'em-midori/core_ext/define_class'
14
+
15
+ require_relative 'em-midori/version'
13
16
  require_relative 'em-midori/const'
14
- require_relative 'em-midori/define_class'
15
17
  require_relative 'em-midori/error'
16
18
  require_relative 'em-midori/clean_room'
17
19
  require_relative 'em-midori/request'
18
20
  require_relative 'em-midori/response'
19
21
  require_relative 'em-midori/api'
22
+ require_relative 'em-midori/api_engine'
20
23
  require_relative 'em-midori/route'
21
24
  require_relative 'em-midori/server'
22
25
  require_relative 'em-midori/websocket'
@@ -2,138 +2,120 @@
2
2
  # This class provides methods to be inherited as route definition.
3
3
  class Midori::API
4
4
  class << self
5
+ attr_accessor :routes, :scope_middlewares
6
+ def class_initialize
7
+ @routes = {
8
+ GET: [],
9
+ POST: [],
10
+ PUT: [],
11
+ DELETE: [],
12
+ OPTIONS: [],
13
+ LINK: [],
14
+ UNLINK: [],
15
+ WEBSOCKET: [],
16
+ EVENTSOURCE: [],
17
+ MOUNT: []
18
+ }
19
+ @scope_middlewares = []
20
+ @temp_middlewares = []
21
+ end
22
+
5
23
  # Add GET method as a DSL for route definition
6
- # @param [ String, Regexp ] path Accepts as part of path in route definition
24
+ # @param [ String ] path Accepts as part of path in route definition
7
25
  # @yield what to run when route matched
8
26
  # @return [ nil ] nil
9
27
  # @example String as router
10
28
  # get '/' do
11
29
  # puts 'Hello World'
12
30
  # end
13
- #
14
- # @example Regex as router
15
- # get /\/hello\/(.*?)/ do
16
- # puts 'Hello World'
17
- # end
18
31
  def get(path, &block) end
19
32
 
20
33
  # Add POST method as a DSL for route definition
21
- # @param [ String, Regexp ] path Accepts as part of path in route definition
34
+ # @param [ String ] path Accepts as part of path in route definition
22
35
  # @yield what to run when route matched
23
36
  # @return [ nil ] nil
24
37
  # @example String as router
25
38
  # post '/' do
26
39
  # puts 'Hello World'
27
40
  # end
28
- #
29
- # @example Regex as router
30
- # post /\/hello\/(.*?)/ do
31
- # puts 'Hello World'
32
- # end
33
41
  def post(path, &block) end
34
42
 
35
43
  # Add PUT method as a DSL for route definition
36
- # @param [ String, Regexp ] path Accepts as part of path in route definition
44
+ # @param [ String ] path Accepts as part of path in route definition
37
45
  # @yield what to run when route matched
38
46
  # @return [ nil ] nil
39
47
  # @example String as router
40
48
  # put '/' do
41
49
  # puts 'Hello World'
42
50
  # end
43
- #
44
- # @example Regex as router
45
- # put /\/hello\/(.*?)/ do
46
- # puts 'Hello World'
47
- # end
48
51
  def put(path, &block) end
49
52
 
50
53
  # Add DELETE method as a DSL for route definition
51
- # @param [ String, Regexp ] path Accepts as part of path in route definition
54
+ # @param [ String ] path Accepts as part of path in route definition
52
55
  # @yield what to run when route matched
53
56
  # @return [ nil ] nil
54
57
  # @example String as router
55
58
  # delete '/' do
56
59
  # puts 'Hello World'
57
60
  # end
58
- #
59
- # @example Regex as router
60
- # delete /\/hello\/(.*?)/ do
61
- # puts 'Hello World'
62
- # end
63
61
  def delete(path, &block) end
64
62
 
65
63
  # Add OPTIONS method as a DSL for route definition
66
- # @param [ String, Regexp ] path Accepts as part of path in route definition
64
+ # @param [ String ] path Accepts as part of path in route definition
67
65
  # @return [ nil ] nil
68
66
  # @example String as router
69
67
  # options '/' do
70
68
  # puts 'Hello World'
71
69
  # end
72
- #
73
- # @example Regex as router
74
- # options /\/hello\/(.*?)/ do
75
- # puts 'Hello World'
76
- # end
77
70
  def options(path, &block) end
78
71
 
79
72
  # Add LINK method as a DSL for route definition
80
- # @param [ String, Regexp ] path Accepts as part of path in route definition
73
+ # @param [ String ] path Accepts as part of path in route definition
81
74
  # @yield what to run when route matched
82
75
  # @return [ nil ] nil
83
76
  # @example String as router
84
77
  # link '/' do
85
78
  # puts 'Hello World'
86
79
  # end
87
- #
88
- # @example Regex as router
89
- # link /\/hello\/(.*?)/ do
90
- # puts 'Hello World'
91
- # end
92
80
  def link(path, &block) end
93
81
 
94
82
  # Add UNLINK method as a DSL for route definition
95
- # @param [ String, Regexp ] path Accepts as part of path in route definition
83
+ # @param [ String ] path Accepts as part of path in route definition
96
84
  # @yield what to run when route matched
97
85
  # @return [ nil ] nil
98
86
  # @example String as router
99
87
  # unlink '/' do
100
88
  # puts 'Hello World'
101
89
  # end
102
- #
103
- # @example Regex as router
104
- # unlink /\/hello\/(.*?)/ do
105
- # puts 'Hello World'
106
- # end
107
90
  def unlink(path, &block) end
108
91
 
109
92
  # Add WEBSOCKET method as a DSL for route definition
110
- # @param [ String, Regexp ] path Accepts as part of path in route definition
93
+ # @param [ String ] path Accepts as part of path in route definition
111
94
  # @yield what to run when route matched
112
95
  # @return [ nil ] nil
113
96
  # @example String as router
114
97
  # websocket '/' do
115
98
  # puts 'Hello World'
116
99
  # end
117
- #
118
- # @example Regex as router
119
- # websocket /\/hello\/(.*?)/ do
120
- # puts 'Hello World'
121
- # end
122
100
  def websocket(path, &block) end
123
101
 
124
102
  # Add EVENTSOURCE method as a DSL for route definition
125
- # @param [ String, Regexp ] path Accepts as part of path in route definition
103
+ # @param [ String ] path Accepts as part of path in route definition
126
104
  # @return [ nil ] nil
127
105
  # @example String as router
128
106
  # eventsource '/' do
129
107
  # puts 'Hello World'
130
108
  # end
131
- #
132
- # @example Regex as router
133
- # eventsource /\/hello\/(.*?)/ do
134
- # puts 'Hello World'
135
- # end
136
109
  def eventsource(path, &block) end
110
+
111
+ # Mount a route prefix with another API defined
112
+ # @param [String] prefix prefix of the route String
113
+ # @param [Class] api inherited from Midori::API
114
+ # @return [nil] nil
115
+ def mount(prefix, api)
116
+ raise ArgumentError if prefix == '/' # Cannot mount route API
117
+ @routes[:MOUNT] << [prefix, api]
118
+ end
137
119
 
138
120
  # Implementation of route DSL
139
121
  # @param [ String ] method HTTP method
@@ -141,82 +123,17 @@ class Midori::API
141
123
  # @param [ Proc ] block process to run when route matched
142
124
  # @return [ nil ] nil
143
125
  def add_route(method, path, block)
144
- if path.class == String
145
- # Convert String to Regexp to provide performance boost (Precompiled Regexp)
146
- path = convert_route path
147
- end
148
- @route = @route || []
149
- @route << Midori::Route.new(method, path, block)
150
- nil
151
- end
126
+ # Argument check
127
+ raise ArgumentError unless path.is_a?String
152
128
 
153
- # Process after receive data from client
154
- # @param request [ Midori::Request ] Http Raw Request
155
- # @param connection [ EM::Connection ] A connection created by EventMachine
156
- # @yield what to run when route matched
157
- # @return [ Midori::Response ] Http Response
158
- # @raise [ Midori::Error::NotFound ] If no route matched
159
- def receive(request, connection = nil)
160
- @route.each do |route|
161
- matched = match(route.method, route.path, request.method, request.path)
162
- next unless matched
163
- if @middleware.nil?
164
- middlewares, body_accept = [], [String]
165
- else
166
- middlewares, body_accept = @middleware.clone, @body_accept.clone
167
- end
168
- middlewares.each { |middleware| request = middleware.before(request) }
169
- clean_room = Midori::CleanRoom.new(request, middlewares, body_accept)
170
- if request.websocket?
171
- # Send 101 Switching Protocol
172
- connection.send_data Midori::Response.new(101, websocket_header(request.header['Sec-WebSocket-Key']), '')
173
- -> { clean_room.instance_exec(connection.websocket, *matched, &route.function) }.call
174
- return Midori::Response.new
175
- elsif request.eventsource?
176
- connection.send_data Midori::Response.new(200, Midori::Const::EVENTSOURCE_HEADER, '')
177
- -> { clean_room.instance_exec(connection.eventsource, *matched, &route.function) }.call
178
- return Midori::Response.new
179
- else
180
- result = -> { clean_room.instance_exec(*matched, &route.function) }.call
181
- clean_room.body = result if body_accept.include?(result.class)
182
- response = clean_room.raw_response
183
- middlewares.reverse_each { |middleware| response = middleware.after(request, response) }
184
- return response
185
- end
186
- end
187
- raise Midori::Error::NotFound
188
- end
129
+ # Insert route to routes
130
+ route = Midori::Route.new(method, path, block)
131
+ route.middlewares = @scope_middlewares + @temp_middlewares
132
+ @routes[method] << route
189
133
 
190
- # Match route with given definition
191
- # @param [ String ] method Accepts an HTTP/1.1 method like GET POST PUT ...
192
- # @param [ Regexp ] path Precompiled route definition.
193
- # @param [ String ] request_method HTTP Request Method
194
- # @param [ String ] request_path HTTP Request Path
195
- # @return [ Array ] matched parameters
196
- # @return [ Boolean ] false if not matched
197
- # @example match a route
198
- # match('GET', /^\/user\/(.*?)\/order\/(.*?)$/, '/user/foo/order/bar') # => ['foo', 'bar']
199
- def match(method, path, request_method, request_path)
200
- if request_method == method
201
- result = request_path.match(path)
202
- return result.to_a[1..-1] if result
203
- false
204
- else
205
- false
206
- end
207
- end
208
-
209
- # Convert String path to its Regexp equivalent
210
- # @param [ String ] path String route definition
211
- # @return [ Regexp ] Regexp equivalent
212
- # @example
213
- # convert_route('/user/:id/order/:order_id') # => Regexp
214
- def convert_route(path)
215
- path = '^' + path
216
- .gsub(/\/(:[_a-z][_a-z0-9]+?)\//, '/([^/]+?)/')
217
- .gsub(/\/(:[_a-z][_a-z0-9]+?)$/, '/([^/]+?)$')
218
- path += '$' if path[-1] != '$'
219
- Regexp.new path
134
+ # Clean up temp middleware
135
+ @temp_middlewares = []
136
+ nil
220
137
  end
221
138
 
222
139
  # Use a middleware in the all routes
@@ -224,20 +141,16 @@ class Midori::API
224
141
  # @return [nil] nil
225
142
  def use(middleware, *args)
226
143
  middleware = middleware.new(*args)
227
- CleanRoom.class_exec { middleware.helper }
228
- @middleware = [] if @middleware.nil?
229
- @middleware << middleware
230
- @body_accept = middleware.body_accept
144
+ Midori::CleanRoom.class_exec { middleware.helper }
145
+ @scope_middlewares << middleware
231
146
  nil
232
147
  end
233
148
 
234
- # Return websocket header with given key
235
- # @param [String] key 'Sec-WebSocket-Key' in request header
236
- # @return [Hash] header
237
- def websocket_header(key)
238
- header = Midori::Const::WEBSOCKET_HEADER.clone
239
- header['Sec-WebSocket-Accept'] = Digest::SHA1.base64digest(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
240
- header
149
+ def filter(middleware, *args)
150
+ middleware = middleware.new(*args)
151
+ Midori::CleanRoom.class_exec { middleware.helper }
152
+ @temp_middlewares << middleware
153
+ nil
241
154
  end
242
155
 
243
156
  # Helper block for defining methods in APIs
@@ -245,6 +158,10 @@ class Midori::API
245
158
  def helper(&block)
246
159
  Midori::CleanRoom.class_exec(&block)
247
160
  end
161
+
162
+ def inherited(subclass)
163
+ subclass.class_initialize
164
+ end
248
165
  end
249
166
 
250
167
  private_class_method :add_route
@@ -255,7 +172,10 @@ class Midori::API
255
172
  # Magics to fill DSL methods through dynamically class method definition
256
173
  METHODS.each do |method|
257
174
  define_singleton_method(method) do |*args, &block|
258
- add_route(method.upcase, args[0], block) # args[0]: path
175
+ add_route(method.upcase.to_sym, args[0], block) # args[0]: path
259
176
  end
260
177
  end
178
+
179
+ singleton_class.send :alias_method, :ws, :websocket
180
+ singleton_class.send :alias_method, :es, :eventsource
261
181
  end
@@ -0,0 +1,84 @@
1
+ class Midori::APIEngine
2
+ attr_accessor :routes
3
+ def initialize(root_api, type = :sinatra)
4
+ @routes = {
5
+ GET: [],
6
+ POST: [],
7
+ PUT: [],
8
+ DELETE: [],
9
+ OPTIONS: [],
10
+ LINK: [],
11
+ UNLINK: [],
12
+ WEBSOCKET: [],
13
+ EVENTSOURCE: []
14
+ }
15
+ @root_api = root_api
16
+ @type = type
17
+ @routes = merge('', root_api, [])
18
+ @routes.delete :MOUNT
19
+ @routes.each do |method|
20
+ method[1].each do |route|
21
+ route.path = Mustermann.new(route.path, type: type)
22
+ end
23
+ end
24
+ end
25
+
26
+ def merge(prefix, root_api, middlewares)
27
+ # Merge all routes with a Depth-first search
28
+ root_api.routes[:MOUNT].each do |mount|
29
+ root_api.routes.merge!(merge(mount[0], mount[1], root_api.scope_middlewares)) do |_key, old_val, new_val|
30
+ old_val + new_val
31
+ end
32
+ end
33
+ root_api.routes.delete :MOUNT
34
+ root_api.routes.each do |method|
35
+ method[1].each do |route|
36
+ route.path = prefix + route.path
37
+ route.middlewares = middlewares + route.middlewares
38
+ end
39
+ end
40
+ root_api.routes
41
+ end
42
+
43
+ # Process after receive data from client
44
+ # @param request [ Midori::Request ] Http Raw Request
45
+ # @param connection [ EM::Connection ] A connection created by EventMachine
46
+ # @return [ Midori::Response ] Http Response
47
+ # @raise [ Midori::Error::NotFound ] If no route matched
48
+ def receive(request, connection = nil)
49
+ @routes[request.method].each do |route|
50
+ params = route.path.params(request.path)
51
+ next unless params
52
+ request.params = params
53
+ route.middlewares.each { |middleware| request = middleware.before(request) }
54
+ clean_room = Midori::CleanRoom.new(request)
55
+ if request.websocket?
56
+ # Send 101 Switching Protocol
57
+ connection.send_data Midori::Response.new(101, Midori::APIEngine.websocket_header(request.header['Sec-WebSocket-Key']), '')
58
+ connection.websocket.request = request
59
+ -> { clean_room.instance_exec(connection.websocket, &route.function) }.call
60
+ return Midori::Response.new
61
+ elsif request.eventsource?
62
+ connection.send_data Midori::Response.new(200, Midori::Const::EVENTSOURCE_HEADER, '')
63
+ -> { clean_room.instance_exec(connection.eventsource, &route.function) }.call
64
+ return Midori::Response.new
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
69
+ route.middlewares.reverse_each { |middleware| response = middleware.after(request, response) }
70
+ return response
71
+ end
72
+ end
73
+ raise Midori::Error::NotFound
74
+ end
75
+
76
+ # Return websocket header with given key
77
+ # @param [String] key 'Sec-WebSocket-Key' in request header
78
+ # @return [Hash] header
79
+ def self.websocket_header(key)
80
+ header = Midori::Const::WEBSOCKET_HEADER.clone
81
+ header['Sec-WebSocket-Accept'] = Digest::SHA1.base64digest(key + '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')
82
+ header
83
+ end
84
+ end
@@ -7,34 +7,16 @@
7
7
  class Midori::CleanRoom
8
8
  attr_accessor :code, :header, :body, :request
9
9
  # @param [Midori::Request] request HTTP request
10
- # @param [Array<Midori::Middleware>] middleware middlewares to run
11
- # @param [Array<Class>] body_accept what class for body could last middleware accept by default
12
- def initialize(request, middleware = [], body_accept = [String])
10
+ def initialize(request)
13
11
  @status = 200
14
12
  @header = Midori::Const::DEFAULT_HEADER.clone
15
13
  @body = ''
16
14
  @request = request
17
- @middleware = middleware
18
- @body_accept = body_accept
19
15
  end
20
16
 
21
- # Genenrate response from variables inside +Midori::CleanRoom+
17
+ # Generate response from variables inside +Midori::CleanRoom+
22
18
  # @return [Midori::Response] midori response
23
19
  def raw_response
24
20
  Midori::Response.new(@status, @header, @body)
25
21
  end
26
-
27
- # Add a middleware to a specific route
28
- # @param [Class] middleware inherited form +Midori::Middleware+ class
29
- # @param [Array<Object>] args for middleware initialize
30
- # @return [nil] nil
31
- def use(middleware, *args)
32
- middleware = middleware.new(*args)
33
- middleware.helper
34
- @middleware = [] if @middleware.nil?
35
- @middleware << middleware
36
- @body_accept.replace middleware.body_accept
37
- @request = middleware.before(request)
38
- nil
39
- end
40
22
  end
@@ -1,9 +1,10 @@
1
1
  ##
2
2
  # Default configuration of Midori, extends +Midori::Configurable+
3
3
  class Midori::Configure
4
- extend Midori::Configurable
4
+ extend Configurable
5
5
 
6
6
  set :logger, ::Logger.new(STDOUT)
7
7
  set :bind, '127.0.0.1'
8
8
  set :port, 8080
9
+ set :route_type, :sinatra
9
10
  end
@@ -1,32 +1,31 @@
1
- module Midori
2
- # Provide flexible configuration for Midori Server
3
- module Configurable
4
- # Modified from Sinatra
5
- # Sets an option to the given value.
6
- # @param [Symbol] option the name of config
7
- # @param [Object] value value to the name
8
- # @param [Boolean] read_only Generate option= method or not
9
- def set(option, value = (not_set = true), read_only = false)
10
- raise ArgumentError if not_set
1
+ ##
2
+ # Modified from Sinatra
3
+ # Provide flexible configuration for Midori Server
4
+ module Configurable
5
+ # Sets an option to the given value.
6
+ # @param [Symbol] option the name of config
7
+ # @param [Object] value value to the name
8
+ # @param [Boolean] read_only Generate option= method or not
9
+ def set(option, value = (not_set = true), read_only = false)
10
+ raise ArgumentError if not_set
11
11
 
12
- setter = proc { |val| set option, val }
13
- getter = proc { value }
12
+ setter = proc { |val| set option, val }
13
+ getter = proc { value }
14
14
 
15
- define_singleton("#{option}=", setter) unless read_only
16
- define_singleton(option, getter)
17
- define_singleton("#{option}?", "!!#{option}") unless method_defined? "#{option}?"
15
+ define_singleton("#{option}=", setter) unless read_only
16
+ define_singleton(option, getter)
17
+ define_singleton("#{option}?", "!!#{option}") unless method_defined? "#{option}?"
18
18
 
19
- self
20
- end
19
+ self
20
+ end
21
21
 
22
- private
22
+ private
23
23
 
24
- # Dynamically defines a method on settings.
25
- def define_singleton(name, content = Proc.new)
26
- singleton_class.class_eval do
27
- undef_method(name) if method_defined? name
28
- String === content ? class_eval("def #{name}() #{content}; end") : define_method(name, &content)
29
- end
24
+ # Dynamically defines a method on settings.
25
+ def define_singleton(name, content = Proc.new)
26
+ singleton_class.class_eval do
27
+ undef_method(name) if method_defined? name
28
+ String === content ? class_eval("def #{name}() #{content}; end") : define_method(name, &content)
30
29
  end
31
30
  end
32
31
  end
@@ -7,9 +7,9 @@ class Promise
7
7
  @callback = callback
8
8
  end
9
9
 
10
- # Define what to do after a method callbacked
11
- # @param [Proc] resolve what if callbacked
12
- # @param [Proc] reject what if callback failed
10
+ # Define what to do after a method callbacks
11
+ # @param [Proc] resolve what on callback
12
+ # @param [Proc] reject what on callback failed
13
13
  # @return [nil] nil
14
14
  def then(resolve = ->() {}, reject = ->() {})
15
15
  @callback.call(resolve, reject)
@@ -24,10 +24,4 @@ class Midori::Middleware
24
24
  # @return [nil] nil
25
25
  def helper
26
26
  end
27
-
28
- # Acceptable body
29
- # @return [Array<Class>] array of acceptable type's class
30
- def body_accept
31
- [String]
32
- end
33
27
  end
@@ -11,7 +11,7 @@
11
11
  class Midori::Request
12
12
  attr_accessor :ip, :port,
13
13
  :protocol, :method, :path, :query_string,
14
- :header, :body, :parsed
14
+ :header, :body, :parsed, :params
15
15
 
16
16
  # Init Request
17
17
  def initialize
@@ -19,6 +19,7 @@ class Midori::Request
19
19
  @is_websocket = false
20
20
  @is_eventsource = false
21
21
  @parser = Http::Parser.new
22
+ @params = {}
22
23
  @parser.on_headers_complete = proc do
23
24
  @protocol = @parser.http_version
24
25
  @method = @parser.http_method
@@ -39,32 +40,33 @@ class Midori::Request
39
40
 
40
41
  # Deal with WebSocket
41
42
  if @header['Upgrade'] == 'websocket' && @header['Connection'] == 'Upgrade'
42
- @method = 'WEBSOCKET'
43
+ @method = :WEBSOCKET
43
44
  @is_websocket = true
44
45
  end
45
46
 
46
47
  # Deal with EventSource
47
48
  if @header['Accept'] == 'text/event-stream'
48
- @method = 'EVENTSOURCE'
49
+ @method = :EVENTSOURCE
49
50
  @is_eventsource = true
50
51
  end
51
52
 
53
+ @method = @method.to_sym
52
54
  @parsed = true
53
55
  end
54
56
 
55
- # Syntatic sugur for whether a request is parsed
57
+ # Syntatic sugar for whether a request is parsed
56
58
  # @return [Boolean] parsed or not
57
59
  def parsed?
58
60
  @parsed
59
61
  end
60
62
 
61
- # Syntatic sugur for whether a request is a websocket request
63
+ # Syntatic sugar for whether a request is a websocket request
62
64
  # @return [Boolean] websocket or not
63
65
  def websocket?
64
66
  @is_websocket
65
67
  end
66
68
 
67
- # Syntatic sugur for whether a request is an eventsource request
69
+ # Syntatic sugar for whether a request is an eventsource request
68
70
  # @return [Boolean] eventsource or not
69
71
  def eventsource?
70
72
  @is_eventsource
@@ -4,7 +4,7 @@
4
4
  # @attr [Regexp] path regex to match
5
5
  # @attr [Proc] function what to do after matched
6
6
  class Midori::Route
7
- attr_accessor :method, :path, :function
7
+ attr_accessor :method, :path, :function, :middlewares
8
8
 
9
9
  # @param [String] method HTTP method
10
10
  # @param [Regexp] path regex to match
@@ -13,5 +13,6 @@ class Midori::Route
13
13
  @method = method
14
14
  @path = path
15
15
  @function = function
16
+ @middlewares = []
16
17
  end
17
18
  end
@@ -7,8 +7,7 @@ class Midori::Runner
7
7
  @logger = configure.logger
8
8
  @bind = configure.bind
9
9
  @port = configure.port
10
-
11
- @api = api
10
+ @api = ((api.is_a?Midori::APIEngine) ? api : Midori::APIEngine.new(api, configure.route_type))
12
11
  end
13
12
 
14
13
  # Get Midori server whether running
@@ -1,5 +1,5 @@
1
1
  # Midori Module
2
2
  module Midori
3
3
  # Current Version Code
4
- VERSION = '0.1.0'.freeze
4
+ VERSION = '0.1.1'.freeze
5
5
  end
@@ -5,7 +5,7 @@
5
5
  # @attr [Hash] events response for different event
6
6
  # @attr [EM::Connection] connection raw EventMachine connection
7
7
  class Midori::WebSocket
8
- attr_accessor :msg, :opcode, :events, :connection
8
+ attr_accessor :msg, :opcode, :events, :connection, :request
9
9
 
10
10
  # @param [EM::Connection] connection raw EventMachine connection
11
11
  def initialize(connection)
@@ -70,7 +70,7 @@ class Midori::WebSocket
70
70
  elsif msg.is_a?Array
71
71
  output << 0b10000010 << msg.size
72
72
  output.concat msg
73
- @connection.send_data(output.pack("C*"))
73
+ @connection.send_data(output.pack('C*'))
74
74
  else
75
75
  raise Midori::Error::OpCodeError
76
76
  end
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.0
4
+ version: 0.1.1
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-10-27 00:00:00.000000000 Z
11
+ date: 2016-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: eventmachine
@@ -17,9 +17,6 @@ dependencies:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.2'
20
- - - ">"
21
- - !ruby/object:Gem::Version
22
- version: 1.2.0.0
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
@@ -27,9 +24,6 @@ dependencies:
27
24
  - - "~>"
28
25
  - !ruby/object:Gem::Version
29
26
  version: '1.2'
30
- - - ">"
31
- - !ruby/object:Gem::Version
32
- version: 1.2.0.0
33
27
  - !ruby/object:Gem::Dependency
34
28
  name: http_parser.rb
35
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,6 +38,20 @@ dependencies:
44
38
  - - "~>"
45
39
  - !ruby/object:Gem::Version
46
40
  version: '0.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: mustermann
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.4'
47
55
  description: EM Midori is an EventMachine-based Web Framework written in pure Ruby,
48
56
  providing high performance and proper abstraction.
49
57
  email: business@heckpsi.com
@@ -51,24 +59,26 @@ executables: []
51
59
  extensions: []
52
60
  extra_rdoc_files: []
53
61
  files:
62
+ - CONTRIBUTOR_COVENANT_CODE_OF_CONDUCT.md
54
63
  - LICENSE
55
64
  - lib/em-midori.rb
56
65
  - lib/em-midori/api.rb
66
+ - lib/em-midori/api_engine.rb
57
67
  - lib/em-midori/clean_room.rb
58
68
  - lib/em-midori/configure.rb
59
69
  - lib/em-midori/const.rb
60
70
  - lib/em-midori/core_ext/configurable.rb
61
- - lib/em-midori/define_class.rb
71
+ - lib/em-midori/core_ext/define_class.rb
72
+ - lib/em-midori/core_ext/promise.rb
73
+ - lib/em-midori/core_ext/string.rb
62
74
  - lib/em-midori/error.rb
63
75
  - lib/em-midori/eventsource.rb
64
76
  - lib/em-midori/middleware.rb
65
- - lib/em-midori/promise.rb
66
77
  - lib/em-midori/request.rb
67
78
  - lib/em-midori/response.rb
68
79
  - lib/em-midori/route.rb
69
80
  - lib/em-midori/runner.rb
70
81
  - lib/em-midori/server.rb
71
- - lib/em-midori/string.rb
72
82
  - lib/em-midori/version.rb
73
83
  - lib/em-midori/websocket.rb
74
84
  homepage: https://github.com/heckpsi-lab/em-midori