em-midori 0.1.0 → 0.1.1

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: 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