keight 0.1.0 → 0.2.0

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: bc49bd013923bbf4714db247133b1dee371519d3
4
- data.tar.gz: f5cda960b9bd0772aae79b835ceca64ae7470c5e
3
+ metadata.gz: 5674423ea6090c2163b9bff12f3ec5f2a1542dce
4
+ data.tar.gz: ecde3e22c5720bfd8be224b45bb3f2e28db092dc
5
5
  SHA512:
6
- metadata.gz: 32ef664b317f9c4053f1bad16e61de02616bcec598d40eb566f278fcc9e87ac35511c6f031cd91a26fae2c06a9de088b2ee8db80530b7966473878f6e613c3d7
7
- data.tar.gz: e45639182983542961cda6d1dfc9bdb7b4e6b282a235162a66dabe74da220bd0cdd46b177d5b4d2410a67ef48fc0d0bfa60dca17bf58fdf559a17b4f65eef4d6
6
+ metadata.gz: 0a976045af16e6ff169a3fe46decb0b9c0fe8d30ed4848dc8d5669298766c3651be375c2dc4690614f3b740c4b599ec209594d82203aaf3e3f05397f1eade1a3
7
+ data.tar.gz: 75720c41ec1250de00b5aeb2c1ed332b674d6c90e7a238bf4263fc1226caf9eedabb9c7d00ca1278f4a9d0609e9f59110d01e0b8e60f7e525d045e01bf744467
@@ -0,0 +1,64 @@
1
+ Changes
2
+ =======
3
+
4
+
5
+ Release 0.2.0 (2016-01-06)
6
+ --------------------------
7
+
8
+ * [change] `K8::RackApplication#mount()` is removed.
9
+ Use `K8::RackApplication.new([...])` instead.
10
+
11
+ * [change] `k8rb init` is renamed to `k8rb project`.
12
+
13
+ $ k8rb project myapp1
14
+ $ cd myapp1
15
+
16
+ * [enhance] Auto redirection support.
17
+ For example, `GET /books` is defined and `GET /books/` is requested,
18
+ then it will be redirected to `GET /books`.
19
+
20
+ * [enhance] Performance improved for variable urlpath.
21
+
22
+ * [enhance] Implement urlpath helpers.
23
+
24
+ p BookAPI[:do_update].method #=> :PUT
25
+ p BookAPI[:do_update].urlpath(123) #=> '/api/books/123'
26
+ p BookAPI[:do_update].form_action_attr(123) #=> '/api/books/123?_method=PUT'
27
+
28
+ * [change] `k8rb mapping` now prints output in text format, not YAML format.
29
+
30
+ * [enhance] `k8rb mapping` supports `--format=FORMAT` option.
31
+
32
+ $ k8rb mapping --format=text # or yaml/json/javascript/jquery/angular
33
+
34
+ * [enhance] `k8rb` command supports `cdnjs` action which download JavaScript
35
+ libraries from cdnjs.com.
36
+
37
+ $ k8rb cdnjs # list library
38
+ $ k8rb cdnjs 'jquery*' # search library
39
+ $ k8rb cdnjs jquery # list versions
40
+ $ k8rb cdnjs jquery 2.1.4 # download library
41
+
42
+ * [change] `k8rb init` command downloads jquery and modernizr from cdnjs.com.
43
+
44
+ * [change] `K8::Mock` and `K8::TestApp` are removed.
45
+ Use rack-test_app gem instead.
46
+
47
+ * [bugfix] Document fixed.
48
+
49
+ * [internal] Remove `K8::ActionClassMapping`, 'K8::ActionRouter' and
50
+ 'K8::ActionFinder' classes.
51
+
52
+ * [internal] Define new class `K8::ActionMapping` instead of remove classes.
53
+
54
+
55
+ Release 0.1.0 (2015-10-27)
56
+ --------------------------
57
+
58
+ * Public release
59
+
60
+
61
+ Release 0.0.1 (2015-10-26)
62
+ --------------------------
63
+
64
+ * Test release
@@ -1,4 +1,4 @@
1
- $Copyright: copyright(c) 2014-2015 kuwata-lab.com all rights reserved $
1
+ $Copyright: copyright(c) 2014-2016 kuwata-lab.com all rights reserved $
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  Keight.rb README
2
2
  ================
3
3
 
4
- ($Release: 0.1.0 $)
4
+ ($Release: 0.2.0 $)
5
5
 
6
6
 
7
7
  Overview
@@ -18,15 +18,15 @@ Benchmarks
18
18
 
19
19
  Measured with `app.call(env)` style in order to exclude server overhead:
20
20
 
21
- | FW | Request | sec/1000req | req/sec |
22
- |:--------|:-------------------|------------:|---------:|
23
- | Rails | GET /api/hello | 7.5188 | 133.0 |
24
- | Rails | GET /api/hello/123 | 8.0030 | 125.0 |
25
- | Sinatra | GET /api/hello | 1.5034 | 665.2 |
26
- | Sinatra | GET /api/hello/123 | 1.6328 | 612.4 |
27
- | Rack | GET /api/hello | 0.0789 | 12674.3 |
28
- | Keight | GET /api/hello | 0.0773 | 12936.6 |
29
- | Keight | GET /api/hello/123 | 0.1385 | 7220.2 |
21
+ | Framework | Request | usec/req | req/sec |
22
+ |:----------|:-------------------|---------:|---------:|
23
+ | Rails | GET /api/hello | 738.7 | 1353.7 |
24
+ | Rails | GET /api/hello/123 | 782.2 | 1278.4 |
25
+ | Sinatra | GET /api/hello | 144.1 | 6938.3 |
26
+ | Sinatra | GET /api/hello/123 | 158.4 | 6313.8 |
27
+ | Rack | GET /api/hello | 9.9 | 101050.9 |
28
+ | Keight | GET /api/hello | 7.6 | 132432.8 |
29
+ | Keight | GET /api/hello/123 | 10.6 | 94705.9 |
30
30
 
31
31
  * Ruby 2.2.3
32
32
  * Rails 4.2.4
@@ -48,7 +48,7 @@ $ export GEM_HOME=$PWD/gems
48
48
  $ export PATH=$GEM_HOME/bin:$PATH
49
49
 
50
50
  $ gem install keight
51
- $ vi hello.rb
51
+ $ vi hello.rb # see below
52
52
  $ vi config.ru # != 'config.rb'
53
53
  $ rackup -p 8000 config.ru
54
54
  ```
@@ -81,44 +81,46 @@ class HelloAction < K8::Action
81
81
  end
82
82
  ```
83
83
 
84
- config.rb:
84
+ config.ru:
85
85
 
86
86
  ```ruby
87
87
  # -*- coding: utf-8 -*-
88
88
  require 'keight'
89
89
  require './hello'
90
90
 
91
- app = K8::RackApplication.new()
92
- app.mount '/hello', HelloAction
93
-
94
- ### or
95
- #mapping = [
96
- # ['/api', [
97
- # ['/hello' , "./hello:HelloAction"],
98
- # ]],
99
- #]
100
- #app = K8::RackApplication.new(mapping)
91
+ mapping = [
92
+ ['/api', [
93
+ ['/hello' , HelloAction],
94
+ ## or
95
+ #['/hello' , "./hello:HelloAction"],
96
+ ]],
97
+ ]
98
+ app = K8::RackApplication.new(mapping)
101
99
 
102
100
  run app
103
101
  ```
104
102
 
105
- Open http://localhost:8000/hello or http://localhost:8000/hello/123
103
+ Open http://localhost:8000/api/hello or http://localhost:8000/api/hello/123
106
104
  with your browser.
107
105
 
108
- Do you like it? If so, try `k8rb init myapp1` to generate project skeleton.
106
+ Do you like it? If so, try `k8rb project myapp1` to generate project skeleton.
109
107
 
110
108
  ```console
111
- $ k8rb init myapp1
109
+ $ mkdir gems # if necessary
110
+ $ export GEM_HOME=$PWD/gems # if necessary
111
+ $ export PATH=$GEM_HOME/bin:$PATH # if necessary
112
+ $ gem install -N keight
113
+ $ k8rb help # show help
114
+ $ k8rb project myapp1 # create new project
112
115
  $ cd myapp1/
116
+ $ rake setup # install gems and download libs
113
117
  $ export APP_ENV=dev # 'dev', 'prod', or 'stg'
114
- $ k8rb mapping
115
- $ k8rb configs
116
- $ rackup -p 8000 -E production config.ru
117
- $ open http://127.0.0.1:8000/
118
- $ ab -n 1000 -c 10 http://127.0.0.1:8000/api/hello
119
- ## or:
120
- $ gem install puma
121
- $ rackup -p 8000 -E production -s puma config.ru
118
+ $ k8rb help mapping
119
+ $ k8rb mapping # list urlpath mappings
120
+ $ k8rb mapping --format=javascript # or jquery,angular,json,yaml
121
+ $ k8rb configs # list config parameters
122
+ $ rake server port=8000
123
+ $ open http://localhost:8000/
122
124
  $ ab -n 10000 -c 100 http://localhost:8000/api/hello
123
125
  ```
124
126
 
@@ -132,8 +134,8 @@ require 'keight'
132
134
  class HelloAction < K8::Action
133
135
 
134
136
  ## mapping
135
- mapping '', :GET=>:do_hello_world
136
- mapping '/{name:[a-zA-Z]+}', :GET=>:do_hello
137
+ mapping '', :GET=>:do_hello_world
138
+ mapping '/{name:\w+}', :GET=>:do_hello
137
139
 
138
140
  ## request, response, and helpers
139
141
 
@@ -199,7 +201,7 @@ class HelloAction < K8::Action
199
201
  end
200
202
 
201
203
  def handle_exception(ex) # exception handler
202
- meth = "on_#{ex.class}"
204
+ meth = "on_#{ex.class.name}"
203
205
  return __send__(meth, ex) if respond_to?(meth)
204
206
  super
205
207
  end
@@ -227,6 +229,144 @@ opts = {
227
229
  urlpath_cache_size: 0, # 0 means cache disabled
228
230
  }
229
231
  app = K8::RackApplication.new(urlpath_mapping, opts)
232
+
233
+ ## misc
234
+ p HelloAction[:do_update].method #=> :GET
235
+ p HelloAction[:do_update].urlpath(123) #=> "/api/books/123"
236
+ p HelloAction[:do_update].form_action_attr(123)
237
+ #=> "/api/books/123?_method=PUT"
238
+ ```
239
+
240
+
241
+ Topics
242
+ ------
243
+
244
+
245
+ ### Make Routing More Faster
246
+
247
+ Specify `urlpath_cache_size: n` (where n is 100 or so) to
248
+ `K8::RackApplication.new()`.
249
+
250
+ ```ruby
251
+ urlpath_mapping = [
252
+ ....
253
+ ]
254
+ rack_app = K8::RackApplication.new(urlpath_mapping,
255
+ urlpath_cache_size: 100) # !!!
256
+ ```
257
+
258
+ In general, there are two type of URL path pattern: fixed and variable.
259
+
260
+ * Fixed URL path pattern doesn't contain any URL path parameter.<br>
261
+ Example: `/`, `/api/books`, `/api/books/new`.
262
+ * Variable URL path pattern contains one or more URL path parameters.<br>
263
+ Example: `/api/books/{id}`, `/api/books/new.{format:html|json}`.
264
+
265
+ Keight.rb caches fixed patterns and doesn't variable ones, therefore
266
+ routing for fixed URL path is faster than variable one.
267
+
268
+ If `urlpath_cache_size: n` is specified, Keight.rb caches latest `n` entries
269
+ of request path matched to variable URL path pattern.
270
+ This will make routing for variable one much faster.
271
+
272
+
273
+ ### Default Pattern of URL Path Parameter
274
+
275
+ URL path parameter `{id}` and `{xxx_id}` are regarded as `{id:\d+}` and
276
+ `{xxx_id:\d+}` respectively and converted into positive interger automatically.
277
+ For example:
278
+
279
+ ```ruby
280
+ class BooksAction < K8::Action
281
+ mapping '/{id}', :GET=>:do_show
282
+ def do_show(id)
283
+ p id.class #=> Fixnum
284
+ ....
285
+ end
286
+ end
287
+ ```
288
+
289
+ URL path parameter `{date}` and `{xxx_date}` are regarded as
290
+ `{date:\d\d\d\d-\d\d-\d\d}` and `{xxx_date:\d\d\d\d-\d\d-\d\d}` respectively
291
+ and converted into Date object automatically.
292
+ For example:
293
+
294
+ ```ruby
295
+ class BlogAPI < K8::Action
296
+ mapping '/{date}', :GET=>:list_entries
297
+ def list_entries(date)
298
+ p date.class #=> Date
299
+ ....
300
+ end
301
+ end
302
+ ```
303
+
304
+ **If you specify `{id:\d+}` or `{date:\d\d\d\d-\d\d-\d\d}` explicitly,
305
+ URL path parameter value is not converted into integer nor Date object.**
306
+ In other words, you can cancel automatic conversion by specifing regular
307
+ expression of URL path parameters.
308
+
309
+
310
+ ### Nested Routing
311
+
312
+ ```ruby
313
+ urlpath_mapping = [
314
+ ['/api', [
315
+ ['/books' , BookAPI],
316
+ ['/books/{book_id}/comments' , BookCommentsAPI],
317
+ ]],
318
+ ]
319
+ ```
320
+
321
+
322
+ ### URL Path Helpers
323
+
324
+ ```ruby
325
+ p BooksAPI[:do_index].method #=> :GET
326
+ p BooksAPI[:do_index].urlpath() #=> "/api/books"
327
+
328
+ p BooksAPI[:do_update].method #=> :PUT
329
+ p BooksAPI[:do_update].urlpath(123) #=> "/api/books/123"
330
+ p BooksAPI[:do_update].form_action_attr(123) #=> "/api/books/123?_method=PUT"
331
+ ```
332
+
333
+ (Notice that these are availabe after `K8::RackApplication` object is created.)
334
+
335
+
336
+ ### Routing for JavaScript
337
+
338
+ Keight.rb can generate JavaScript routing file.
339
+
340
+ ```console
341
+ $ k8rb project myapp1
342
+ $ cd myapp1/
343
+ $ k8rb mapping --format=javascript | less # or 'jquery', 'angular'
344
+ $ mkdir -p static/js
345
+ $ jsfile=static/js/urlpath_mapping.js
346
+ $ rm -f $jsfile
347
+ $ echo 'var Mapping = {' >> $jsfile
348
+ $ k8rb mapping --format=javascript >> $jsfile
349
+ $ echo '};' >> $jsfile
350
+ ```
351
+
352
+
353
+ ### Download JavaScript Libraries
354
+
355
+ Keight.rb can download Javascript or CSS libraries from [cdnjs.com].
356
+ It is good idea to make layout of JavaScript libraries to be same as CDN.
357
+
358
+ [cdnjs.com]: https://cdnjs.com/
359
+
360
+ ```console
361
+ $ k8rb project myapp1
362
+ $ cd myapp1/
363
+ $ k8rb help cdnjs
364
+ $ k8rb cdnjs # list libraries
365
+ $ k8rb cdnjs 'jquery*' # search libraries
366
+ $ k8rb cdnjs jquery # list versions
367
+ $ k8rb cdnjs jquery 2.1.4 # download library
368
+ ## or
369
+ $ k8rb cdnjs --basedir=static/lib jquery 2.1.4
230
370
  ```
231
371
 
232
372
 
@@ -242,17 +382,17 @@ I don't think Keight.rb is so fast. Other frameworks are just too slow.
242
382
 
243
383
  #### How to setup template engine?
244
384
 
245
- Try `k8rb init myapp1; cd myapp1; less app/action.rb`.
385
+ Try `k8rb project myapp1; cd myapp1; less app/action.rb`.
246
386
 
247
387
 
248
388
  #### How to support static files?
249
389
 
250
- Try `k8rb init myapp1; cd myapp1; less app/action.rb`.
390
+ Try `k8rb project myapp1; cd myapp1; less app/action.rb`.
251
391
 
252
392
 
253
393
  #### How to setup session?
254
394
 
255
- Try `k8rb init myapp1; cd myapp1; less config.ru`.
395
+ Try `k8rb project myapp1; cd myapp1; less config.ru`.
256
396
 
257
397
 
258
398
  #### Can I use Rack::Request and Rack::Response instead of Keight's?
@@ -260,24 +400,9 @@ Try `k8rb init myapp1; cd myapp1; less config.ru`.
260
400
  Try `K8::REQUEST_CLASS = Rack::Request; K8::RESPONSE_CLASS = Rack::Response`.
261
401
 
262
402
 
263
- #### What `urlpath_cache_size: 0` means?
264
-
265
- `K8::RackApplication` can take `urlpath_cache_size: n` keyword arugment.
266
-
267
- * If `n == 0` then Keight.rb doesn't cache urlpath mapping containig
268
- urlpath parameters such as `/api/books/{id}`.
269
- * If `n > 0` then Keight.rb caches latest `n` entries of urlpath mapping
270
- containing urlpath parameters.
271
- * Keight.rb always caches urlpath mapping which has no urlpath parameters.
272
- For example, `/api/books` is always cached regardless
273
- `urlpath_cache_size:` value.
274
-
275
- If you need more performance, try `urlpath_cache_size: 1000` or so.
276
-
277
-
278
403
  License and Copyright
279
404
  ---------------------
280
405
 
281
406
  $License: MIT License $
282
407
 
283
- $Copyright: copyright(c) 2014-2015 kuwata-lab.com all rights reserved $
408
+ $Copyright: copyright(c) 2014-2016 kuwata-lab.com all rights reserved $
data/Rakefile CHANGED
@@ -3,7 +3,7 @@
3
3
  ###
4
4
 
5
5
  RELEASE = ENV['rel'] || '0.0.0'
6
- COPYRIGHT = 'copyright(c) 2014-2015 kuwata-lab.com all rights reserved'
6
+ COPYRIGHT = 'copyright(c) 2014-2016 kuwata-lab.com all rights reserved'
7
7
  LICENSE = 'MIT License'
8
8
 
9
9
  PROJECT = 'keight'
@@ -2,13 +2,31 @@
2
2
 
3
3
  $LOAD_PATH << '.'
4
4
 
5
- require 'rack'
6
- require 'sinatra/base' rescue nil
7
- require 'rack-multiplexer' rescue nil
8
- require 'keight' rescue nil
5
+ def _version(cmdopt)
6
+ if cmdopt == '0'
7
+ return nil
8
+ end
9
+ begin
10
+ return yield
11
+ rescue LoadError
12
+ if cmdopt.to_s.empty?
13
+ return nil
14
+ else
15
+ raise
16
+ end
17
+ end
18
+ end
19
+
20
+ version_rack = _version($rack) { require 'rack' ; Rack.release }
21
+ version_sina = _version($sina) { require 'sinatra/base' ; Sinatra::VERSION }
22
+ version_mplx = _version($mplx) { require 'rack/multiplexer'; Rack::Multiplexer::VERSION }
23
+ version_k8 = _version($k8 ) { require 'keight' ; K8::RELEASE }
24
+ version_jet = _version($jet ) { require 'rack/jet_router' ; Rack::JetRouter::RELEASE }
9
25
 
26
+ $api_entries = ('a'..'z').each_with_index.map {|x, i| "%s%02d" % [x*3, i+1] }
10
27
 
11
- if defined?(Rack)
28
+
29
+ if version_rack
12
30
 
13
31
  class RackApp1
14
32
  def call(env)
@@ -48,14 +66,15 @@ if defined?(Rack)
48
66
  end
49
67
 
50
68
 
51
- $api_entries = %w[books authors account orders ranking about news support]
52
- $admin_entries = ('a'..'z').each_with_index.collect {|c,i| "%s%02d" % [c*3, i+1] }
53
-
54
-
55
- if defined?(Sinatra)
69
+ if version_sina
56
70
 
57
71
  class SinaApp < Sinatra::Base
58
72
 
73
+ set :sessions , false
74
+ set :logging , false
75
+ set :protection , false
76
+ set :x_cascade , false
77
+
59
78
  for x in $api_entries
60
79
  get "/api/#{x}" do "<h1>index</h1>" end
61
80
  post "/api/#{x}" do "<h1>create</h1>" end
@@ -66,14 +85,6 @@ if defined?(Sinatra)
66
85
  #get "/api/#{x}/:id/edit" do "<h1>edit</h1>" end
67
86
  end
68
87
 
69
- for x in $admin_entries # 'aaa01', 'bbb02', ..., 'zzz26'
70
- get "/admin/#{x}" do '<p>index</p>' end
71
- post "/admin/#{x}" do '<p>create</p>' end
72
- get "/admin/#{x}/:id" do '<p>show</p>' end
73
- put "/admin/#{x}/:id" do '<p>update</p>' end
74
- delete "/admin/#{x}/:id" do '<p>delete</p>' end
75
- end
76
-
77
88
  end
78
89
 
79
90
  sina_app = SinaApp.new
@@ -81,67 +92,35 @@ if defined?(Sinatra)
81
92
  end
82
93
 
83
94
 
84
- if defined?(Rack::Multiplexer)
85
-
86
- mplx_dummy = proc {|env|
87
- [200, {"Content-Type"=>"text/html"}, ["<h1>hello</h1>"]]
88
- #req = Rack::Request.new(env)
89
- #resp = Rack::Response.new
90
- #[resp.status, resp.headers, ["<h1>index</h1>"]]
91
- }
92
-
93
- mplx_app1 = Rack::Multiplexer.new
94
-
95
- for x in $api_entries
96
- mplx_app1.get "/api/#{x}", mplx_dummy
97
- mplx_app1.post "/api/#{x}", mplx_dummy
98
- #mplx_app1.get "/api/#{x}/new", mplx_dummy
99
- mplx_app1.get "/api/#{x}/:id", mplx_dummy
100
- mplx_app1.post "/api/#{x}/:id", mplx_dummy
101
- mplx_app1.delete "/api/#{x}/:id", mplx_dummy
102
- #mplx_app1.get "/api/#{x}/:id/edit", mplx_dummy
103
- end
104
- for x in $admin_entries # 'aaa01', 'bbb02', ..., 'zzz26'
105
- mplx_app1.get "/admin/#{x}", mplx_dummy
106
- mplx_app1.post "/admin/#{x}", mplx_dummy
107
- mplx_app1.get "/admin/#{x}/:id", mplx_dummy
108
- mplx_app1.put "/admin/#{x}/:id", mplx_dummy
109
- mplx_app1.delete "/admin/#{x}/:id", mplx_dummy
110
- end
95
+ if version_mplx
111
96
 
112
- mplx_api = Rack::Multiplexer.new
113
- for x in $api_entries
114
- mplx_api.get "/api/#{x}", mplx_dummy
115
- mplx_api.post "/api/#{x}", mplx_dummy
116
- #mplx_api.get "/api/#{x}/new", mplx_dummy
117
- mplx_api.get "/api/#{x}/:id", mplx_dummy
118
- mplx_api.post "/api/#{x}/:id", mplx_dummy
119
- mplx_api.delete "/api/#{x}/:id", mplx_dummy
120
- #mplx_api.get "/api/#{x}/:id/edit", mplx_dummy
121
- end
122
- mplx_admin = Rack::Multiplexer.new
123
- for x in $admin_entries # 'aaa01', 'bbb02', ..., 'zzz26'
124
- mplx_admin.get "/admin/#{x}", mplx_dummy
125
- mplx_admin.post "/admin/#{x}", mplx_dummy
126
- mplx_admin.get "/admin/#{x}/:id", mplx_dummy
127
- mplx_admin.put "/admin/#{x}/:id", mplx_dummy
128
- mplx_admin.delete "/admin/#{x}/:id", mplx_dummy
129
- end
130
- mplx_app2 = proc {|env|
131
- urlpath = env['PATH_INFO']
132
- if urlpath.start_with?('/api')
133
- mplx_api.call(env)
134
- elsif urlpath.start_with?('/admin')
135
- mplx_admin.call(env)
136
- else
137
- [404, {}, []]
97
+ mplx_app = proc {
98
+ #
99
+ proc_ = proc {|env|
100
+ [200, {"Content-Type"=>"text/html"}, ["<h1>hello</h1>"]]
101
+ #req = Rack::Request.new(env)
102
+ #resp = Rack::Response.new
103
+ #[resp.status, resp.headers, ["<h1>index</h1>"]]
104
+ }
105
+ #
106
+ app = Rack::Multiplexer.new
107
+ for x in $api_entries
108
+ app.get "/api/#{x}", proc_
109
+ app.post "/api/#{x}", proc_
110
+ #app.get "/api/#{x}/new", proc_
111
+ app.get "/api/#{x}/:id", proc_
112
+ app.post "/api/#{x}/:id", proc_
113
+ app.delete "/api/#{x}/:id", proc_
114
+ #app.get "/api/#{x}/:id/edit", proc_
138
115
  end
139
- }
116
+ #
117
+ app
118
+ }.call()
140
119
 
141
120
  end
142
121
 
143
122
 
144
- if defined?(K8)
123
+ if version_k8
145
124
 
146
125
  class DummyAction < K8::Action
147
126
  mapping '', :GET=>:do_index, :POST=>:do_create
@@ -157,37 +136,59 @@ if defined?(K8)
157
136
  def do_edit(id) ; "<h1>edit</h1>"; end
158
137
  end
159
138
  #
160
- k8_app_opts = {urlpath_cache_size: 0}
161
- k8_app = K8::RackApplication.new(k8_app_opts)
162
- k8_app.mount '/api', [
163
- ['/books', DummyAction],
164
- ['/books/{id}/comments', DummyAction],
165
- ['/authors', DummyAction],
166
- ['/authors/{id}/comments', DummyAction],
167
- ['/account', DummyAction],
168
- ['/orders', DummyAction],
169
- ['/ranking', DummyAction],
170
- ['/about', DummyAction],
171
- ['/news', DummyAction],
172
- ['/support', DummyAction],
173
- ]
174
- pairs = $admin_entries.collect {|x| # 'aaa01', 'bbb02', ..., 'zzz26'
175
- ["/#{x}", DummyAction]
176
- }
177
- k8_app.mount '/admin', pairs
178
- #
179
- k8_app.find('/') # warm up
139
+ k8_app = proc {
140
+ mapping = [
141
+ ['/api', $api_entries.map {|x| ["/#{x}", DummyAction] }],
142
+ ]
143
+ opts = {
144
+ urlpath_cache_size: ($k8size || 0).to_i,
145
+ enable_urlpath_param_range: $k8range != '0',
146
+ }
147
+ K8::RackApplication.new(mapping, opts)
148
+ }.call()
149
+
150
+ end
151
+
152
+
153
+ if version_jet
154
+
155
+ jet_app = proc {
156
+ #
157
+ jet_proc = proc {|env|
158
+ [200, {"Content-Type"=>"text/html"}, ["<h1>hello</h1>"]]
159
+ #req = Rack::Request.new(env)
160
+ #resp = Rack::Response.new
161
+ #[resp.status, resp.headers, ["<h1>index</h1>"]]
162
+ }
163
+ methods1 = {:GET=>jet_proc, :POST=>jet_proc}
164
+ methods2 = {:GET=>jet_proc, :PUT=>jet_proc, :DELETE=>jet_proc}
165
+ #
166
+ arr = $api_entries.map {|x| ["/#{x}", [['', methods1], ['/:id', methods2]]] }
167
+ jet_mapping = [
168
+ ['/api', $api_entries.map {|x| ["/#{x}", [
169
+ ['', methods1],
170
+ ['/:id', methods2],
171
+ ]] }
172
+ ],
173
+ ]
174
+ #
175
+ jet_opts = {
176
+ urlpath_cache_size: ($jetcache || 0).to_i,
177
+ enable_urlpath_param_range: $jetrange != '0',
178
+ }
179
+ #
180
+ Rack::JetRouter.new(jet_mapping, jet_opts)
181
+ }.call()
180
182
 
181
183
  end
182
184
 
183
185
 
184
186
  def _chk(tuple)
185
187
  tuple[0] == 200 or raise "200 expected but got #{tuple[0]}"
186
- GC.start
187
188
  end
188
189
 
189
- $environ = Rack::MockRequest.env_for("http://localhost/")
190
- $environ['REQUEST_METHOD'] = 'GET'
190
+ require 'rack' unless defined?(Rack)
191
+ $environ = Rack::MockRequest.env_for("http://localhost/", method: 'GET')
191
192
 
192
193
  def newenv(path)
193
194
  env = $environ.dup
@@ -198,21 +199,27 @@ end
198
199
 
199
200
  require 'benchmarker'
200
201
 
202
+ N = ($N || 100000).to_i
201
203
 
202
- Benchmarker.new(:width=>30, :loop=>100000) do |bm|
203
-
204
- flag_rack = flag_sinatra = flag_multiplexer = flag_keight = false
205
- flag_rack = defined?(Rack)
206
- #flag_sinatra = defined?(Sinatra)
207
- flag_multiplexer = defined?(Rack::Multiplexer)
208
- flag_keight = defined?(K8)
209
-
210
- urlpaths = %w[/api/books /api/books/123 /api/support /api/support/123
211
- /admin/aaa01 /admin/aaa01/123 /admin/zzz26 /admin/zzz26/123]
204
+ Benchmarker.new(:width=>30, :loop=>N) do |bm|
212
205
 
206
+ urlpaths = [
207
+ '/api/aaa01',
208
+ '/api/aaa01/123',
209
+ '/api/zzz26',
210
+ '/api/zzz26/789',
211
+ ]
213
212
 
214
213
  tuple = nil
215
214
 
215
+ puts ""
216
+ puts "** rack : #{version_rack || '-'}"
217
+ puts "** rack-jet_router : #{version_jet || '-'}"
218
+ puts "** rack-multiplexer: #{version_mplx || '-'}"
219
+ puts "** sinatra : #{version_sina || '-'}"
220
+ puts "** keight : #{version_k8 || '-'}"
221
+ puts ""
222
+ puts "** N=#{N}"
216
223
 
217
224
  ### empty task
218
225
 
@@ -222,10 +229,11 @@ Benchmarker.new(:width=>30, :loop=>100000) do |bm|
222
229
 
223
230
 
224
231
  ### Rack
225
- if flag_rack
232
+ if version_rack
233
+ rack_labels = ['Rack', 'R:Rq', 'R:Rs', 'RqRs']
226
234
  rack_apps = [rack_app1, rack_app2, rack_app3, rack_app4]
227
- for rack_app, i in rack_apps.each_with_index
228
- bm.task("(Rack#{i+1}) /some/where") do
235
+ for rack_app, label in rack_apps.zip(rack_labels)
236
+ bm.task("(#{label}) /some/where") do
229
237
  tuple = rack_app.call(newenv("/some/where"))
230
238
  end
231
239
  _chk(tuple)
@@ -234,7 +242,7 @@ Benchmarker.new(:width=>30, :loop=>100000) do |bm|
234
242
 
235
243
 
236
244
  ### Sinatra
237
- if flag_sinatra
245
+ if version_sina
238
246
  for upath in urlpaths
239
247
  bm.task("(Sina) #{upath}") do
240
248
  tuple = sina_app.call(newenv(upath))
@@ -245,34 +253,126 @@ Benchmarker.new(:width=>30, :loop=>100000) do |bm|
245
253
 
246
254
 
247
255
  ### Rack::Multiplexer
248
- if flag_multiplexer
256
+ if version_mplx
249
257
  for upath in urlpaths
250
258
  bm.task("(Mplx) #{upath}") do
251
- tuple = mplx_app1.call(newenv(upath))
259
+ tuple = mplx_app.call(newenv(upath))
252
260
  end
253
261
  _chk(tuple)
254
262
  end
255
263
  end
256
264
 
257
- if flag_multiplexer
265
+
266
+ ### Keight
267
+
268
+ if version_k8
258
269
  for upath in urlpaths
259
- bm.task("(Mplx') #{upath}") do
260
- tuple = mplx_app2.call(newenv(upath))
270
+ bm.task("(K8 ) #{upath}") do
271
+ tuple = k8_app.call(newenv(upath))
261
272
  end
262
273
  _chk(tuple)
263
274
  end
264
275
  end
265
276
 
266
277
 
267
- ### Keight
278
+ ### Rack::JetRouter
268
279
 
269
- if flag_keight
280
+ if version_jet
270
281
  for upath in urlpaths
271
- bm.task("(K8) #{upath}") do
272
- tuple = k8_app.call(newenv(upath))
282
+ bm.task("(JetR) #{upath}") do
283
+ tuple = jet_app.call(newenv(upath))
273
284
  end
274
285
  _chk(tuple)
275
286
  end
276
287
  end
277
288
 
278
289
  end
290
+
291
+
292
+ __END__
293
+
294
+ ###
295
+ ### Example result
296
+ ###
297
+
298
+ $ ruby -I../lib -I. -s bench.rb -N=1000000
299
+
300
+ benchmarker.rb: release 0.0.0
301
+ RUBY_VERSION: 2.3.0
302
+ RUBY_PATCHLEVEL: 0
303
+ RUBY_PLATFORM: x86_64-darwin15
304
+
305
+ ** rack : 1.6.4
306
+ ** rack-jet_router : 1.1.0
307
+ ** rack-multiplexer: 0.0.8
308
+ ** sinatra : 1.4.6
309
+ ** keight : 0.2.0
310
+
311
+ ** N=1000000
312
+
313
+ ## user sys total real
314
+ (Empty) 7.3000 0.0900 7.3900 7.4131
315
+ (Rack) /some/where 0.8400 -0.0400 0.8000 0.7903
316
+ (R:Rq) /some/where 0.8400 -0.0500 0.7900 0.7743
317
+ (R:Rs) /some/where 6.1600 -0.0500 6.1100 6.0898
318
+ (RqRs) /some/where 6.4200 -0.0600 6.3600 6.3407
319
+ (Sina) /api/aaa01 84.5700 18.0800 102.6500 102.7069
320
+ (Sina) /api/aaa01/123 94.1300 18.4800 112.6100 112.6892
321
+ (Sina) /api/zzz26 125.7300 19.0800 144.8100 145.0454
322
+ (Sina) /api/zzz26/789 133.8000 18.9600 152.7600 152.9070
323
+ (Mplx) /api/aaa01 5.0200 0.1700 5.1900 5.1821
324
+ (Mplx) /api/aaa01/123 16.7100 0.3100 17.0200 17.0086
325
+ (Mplx) /api/zzz26 23.3700 -0.0400 23.3300 23.3190
326
+ (Mplx) /api/zzz26/789 35.6500 0.0100 35.6600 35.6661
327
+ (K8 ) /api/aaa01 5.9200 0.0300 5.9500 5.9423
328
+ (K8 ) /api/aaa01/123 9.2200 0.0900 9.3100 9.2934
329
+ (K8 ) /api/zzz26 6.2700 0.0600 6.3300 6.3158
330
+ (K8 ) /api/zzz26/789 10.0300 0.1300 10.1600 10.1547
331
+ (JetR) /api/aaa01 1.1800 0.0400 1.2200 1.2154
332
+ (JetR) /api/aaa01/123 5.0400 0.1100 5.1500 5.1431
333
+ (JetR) /api/zzz26 0.9600 0.0300 0.9900 0.9681
334
+ (JetR) /api/zzz26/789 5.6900 0.1100 5.8000 5.7946
335
+
336
+ ## Ranking real
337
+ (R:Rq) /some/where 0.7743 (100.0%) ********************
338
+ (Rack) /some/where 0.7903 ( 98.0%) ********************
339
+ (JetR) /api/zzz26 0.9681 ( 80.0%) ****************
340
+ (JetR) /api/aaa01 1.2154 ( 63.7%) *************
341
+ (JetR) /api/aaa01/123 5.1431 ( 15.1%) ***
342
+ (Mplx) /api/aaa01 5.1821 ( 14.9%) ***
343
+ (JetR) /api/zzz26/789 5.7946 ( 13.4%) ***
344
+ (K8 ) /api/aaa01 5.9423 ( 13.0%) ***
345
+ (R:Rs) /some/where 6.0898 ( 12.7%) ***
346
+ (K8 ) /api/zzz26 6.3158 ( 12.3%) **
347
+ (RqRs) /some/where 6.3407 ( 12.2%) **
348
+ (K8 ) /api/aaa01/123 9.2934 ( 8.3%) **
349
+ (K8 ) /api/zzz26/789 10.1547 ( 7.6%) **
350
+ (Mplx) /api/aaa01/123 17.0086 ( 4.6%) *
351
+ (Mplx) /api/zzz26 23.3190 ( 3.3%) *
352
+ (Mplx) /api/zzz26/789 35.6661 ( 2.2%)
353
+ (Sina) /api/aaa01 102.7069 ( 0.8%)
354
+ (Sina) /api/aaa01/123 112.6892 ( 0.7%)
355
+ (Sina) /api/zzz26 145.0454 ( 0.5%)
356
+ (Sina) /api/zzz26/789 152.9070 ( 0.5%)
357
+
358
+ ## Matrix real [01] [02] [03] [04] [05] [06] [07] [08] [09] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20]
359
+ [01] (Rack2) /some/where 0.7743 100.0% 102.1% 125.0% 157.0% 664.2% 669.2% 748.3% 767.4% 786.5% 815.6% 818.9% 1200.2% 1311.4% 2196.6% 3011.5% 4606.1% 13264.0% 14553.1% 18731.7% 19747.0%
360
+ [02] (Rack1) /some/where 0.7903 98.0% 100.0% 122.5% 153.8% 650.7% 655.7% 733.2% 751.9% 770.5% 799.1% 802.3% 1175.9% 1284.8% 2152.1% 2950.5% 4512.7% 12995.2% 14258.3% 18352.2% 19346.9%
361
+ [03] (JetR) /api/zzz26 0.9681 80.0% 81.6% 100.0% 125.5% 531.2% 535.3% 598.5% 613.8% 629.0% 652.4% 654.9% 959.9% 1048.9% 1756.9% 2408.7% 3684.0% 10608.8% 11639.9% 14982.1% 15794.1%
362
+ [04] (JetR) /api/aaa01 1.2154 63.7% 65.0% 79.7% 100.0% 423.2% 426.4% 476.8% 488.9% 501.0% 519.6% 521.7% 764.6% 835.5% 1399.4% 1918.6% 2934.5% 8450.4% 9271.7% 11933.8% 12580.6%
363
+ [05] (JetR) /api/aaa01/123 5.1431 15.1% 15.4% 18.8% 23.6% 100.0% 100.8% 112.7% 115.5% 118.4% 122.8% 123.3% 180.7% 197.4% 330.7% 453.4% 693.5% 1997.0% 2191.1% 2820.2% 2973.1%
364
+ [06] (Mplx) /api/aaa01 5.1821 14.9% 15.3% 18.7% 23.5% 99.2% 100.0% 111.8% 114.7% 117.5% 121.9% 122.4% 179.3% 196.0% 328.2% 450.0% 688.3% 1982.0% 2174.6% 2799.0% 2950.7%
365
+ [07] (JetR) /api/zzz26/789 5.7946 13.4% 13.6% 16.7% 21.0% 88.8% 89.4% 100.0% 102.5% 105.1% 109.0% 109.4% 160.4% 175.2% 293.5% 402.4% 615.5% 1772.5% 1944.7% 2503.1% 2638.8%
366
+ [08] (K8) /api/aaa01 5.9423 13.0% 13.3% 16.3% 20.5% 86.6% 87.2% 97.5% 100.0% 102.5% 106.3% 106.7% 156.4% 170.9% 286.2% 392.4% 600.2% 1728.4% 1896.4% 2440.9% 2573.2%
367
+ [09] (Rack3) /some/where 6.0898 12.7% 13.0% 15.9% 20.0% 84.5% 85.1% 95.2% 97.6% 100.0% 103.7% 104.1% 152.6% 166.7% 279.3% 382.9% 585.7% 1686.5% 1850.5% 2381.8% 2510.9%
368
+ [10] (K8) /api/zzz26 6.3158 12.3% 12.5% 15.3% 19.2% 81.4% 82.0% 91.7% 94.1% 96.4% 100.0% 100.4% 147.1% 160.8% 269.3% 369.2% 564.7% 1626.2% 1784.3% 2296.6% 2421.0%
369
+ [11] (Rack4) /some/where 6.3407 12.2% 12.5% 15.3% 19.2% 81.1% 81.7% 91.4% 93.7% 96.0% 99.6% 100.0% 146.6% 160.2% 268.2% 367.8% 562.5% 1619.8% 1777.2% 2287.5% 2411.5%
370
+ [12] (K8) /api/aaa01/123 9.2934 8.3% 8.5% 10.4% 13.1% 55.3% 55.8% 62.4% 63.9% 65.5% 68.0% 68.2% 100.0% 109.3% 183.0% 250.9% 383.8% 1105.2% 1212.6% 1560.7% 1645.3%
371
+ [13] (K8) /api/zzz26/789 10.1547 7.6% 7.8% 9.5% 12.0% 50.6% 51.0% 57.1% 58.5% 60.0% 62.2% 62.4% 91.5% 100.0% 167.5% 229.6% 351.2% 1011.4% 1109.7% 1428.4% 1505.8%
372
+ [14] (Mplx) /api/aaa01/123 17.0086 4.6% 4.6% 5.7% 7.1% 30.2% 30.5% 34.1% 34.9% 35.8% 37.1% 37.3% 54.6% 59.7% 100.0% 137.1% 209.7% 603.9% 662.5% 852.8% 899.0%
373
+ [15] (Mplx) /api/zzz26 23.3190 3.3% 3.4% 4.2% 5.2% 22.1% 22.2% 24.8% 25.5% 26.1% 27.1% 27.2% 39.9% 43.5% 72.9% 100.0% 152.9% 440.4% 483.3% 622.0% 655.7%
374
+ [16] (Mplx) /api/zzz26/789 35.6661 2.2% 2.2% 2.7% 3.4% 14.4% 14.5% 16.2% 16.7% 17.1% 17.7% 17.8% 26.1% 28.5% 47.7% 65.4% 100.0% 288.0% 316.0% 406.7% 428.7%
375
+ [17] (Sina) /api/aaa01 102.7069 0.8% 0.8% 0.9% 1.2% 5.0% 5.0% 5.6% 5.8% 5.9% 6.1% 6.2% 9.0% 9.9% 16.6% 22.7% 34.7% 100.0% 109.7% 141.2% 148.9%
376
+ [18] (Sina) /api/aaa01/123 112.6892 0.7% 0.7% 0.9% 1.1% 4.6% 4.6% 5.1% 5.3% 5.4% 5.6% 5.6% 8.2% 9.0% 15.1% 20.7% 31.6% 91.1% 100.0% 128.7% 135.7%
377
+ [19] (Sina) /api/zzz26 145.0454 0.5% 0.5% 0.7% 0.8% 3.5% 3.6% 4.0% 4.1% 4.2% 4.4% 4.4% 6.4% 7.0% 11.7% 16.1% 24.6% 70.8% 77.7% 100.0% 105.4%
378
+ [20] (Sina) /api/zzz26/789 152.9070 0.5% 0.5% 0.6% 0.8% 3.4% 3.4% 3.8% 3.9% 4.0% 4.1% 4.1% 6.1% 6.6% 11.1% 15.3% 23.3% 67.2% 73.7% 94.9% 100.0%