rack-jet_router 1.2.0 → 1.3.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
- SHA1:
3
- metadata.gz: dbed04ca4adfdce5a3e82234dd6182e18519dc62
4
- data.tar.gz: bdec9db77792ffba5bca3e05ae4bf62f35cbf555
2
+ SHA256:
3
+ metadata.gz: ffb2322f3ac227a3d07fa95c120d25c3dcb8763f9ea925be7a3a03df11c00ba9
4
+ data.tar.gz: 60b292dd4a1307a2fd1cbfcb474746131599fe0ba0ae93768b40f2cf0c9e5fa5
5
5
  SHA512:
6
- metadata.gz: 0d90ffbb230351b7f0054d7d382b377dca41832cbfe2a47d6793c0ac88dbc075104535bf4529a6e1c50251365faadefb8d1fa02342d7104420cd8eb6316ea495
7
- data.tar.gz: af141052683402fd8dedc4538b548bab59c816714e423236fe83cd70d2865f77337f5c6b9e0d93380e49fe4547995e36f256943be6426a20b1d04a82cfe69697
6
+ metadata.gz: d33fb4622786b549f6681f6a89fd578f631235548b7d67644431483815a71e62d0a438c22b82e2534074c52e704cd68607f02060153ea8477898e13725c3e836
7
+ data.tar.gz: 36be6953b2ed04a82f56c97e0c3eaf51022b21546116a0ead5b1a125ff82c746c1297a9c4e153012ca0a922e1a55161a1ea7a534036857d97cd91529aa4118d9
data/CHANGES.md ADDED
@@ -0,0 +1,52 @@
1
+ CHANGES
2
+ =======
3
+
4
+
5
+ Release 1.3.0 (2023-12-09)
6
+ --------------------------
7
+
8
+ * [enhance] Performance has improved (about 10%). This improvement was achieved by optimizing regular expressions.
9
+ * [enhance] URL path mapping can be nested Hash as well as nested Array. See the document for detail.
10
+ * [enhance] Passing the `int_param: /(?:\A|_)id\z/` keyword argument to `JetRouter.new()` changes the router to treat urlpath parameter `id` or `xxx_id` as integer type.
11
+ * [enhance] Passing the `env_key:` keyword argument to `JetRouter.new()` changes the key of environemnt to store URL path parameter values.
12
+ * [change] Keyword parameter `urlpath_cache_size:` of `JetRouter.new()` is renamed to `cache_size:`. Old parameter name is also available for backward compatibility, but it is recommended to use new parameter name.
13
+ * [change] Rename `JetRouter#build_urlpath_parameter_vars()` to `JetRouter#build_param_values()`.
14
+ * [change] Update benchmark script to require 'benchmarker' gem.
15
+
16
+
17
+ Release 1.2.0 (2016-10-16)
18
+ --------------------------
19
+
20
+ * Change auto-redirection to be occurred only on GET or HEAD methods.
21
+ * Code is rewrited, especially around `Rack::JetRouter#compile_mapping()`.
22
+ * Update benchmark script to support `Hanabi::Router`.
23
+
24
+
25
+ Release 1.1.1 (2015-12-29)
26
+ --------------------------
27
+
28
+ * Fix benchmark script.
29
+ * Fix document.
30
+
31
+
32
+ Release 1.1.0 (2015-12-28)
33
+ --------------------------
34
+
35
+ * **NOTICE** `Rack::JetRouter#find()` is renamed to `#lookup()`.
36
+ `#find()` is also available for compatibility, but not recommended.
37
+ * Performance improved when number of URL path parameter is 1.
38
+ * Regular expression generated is improved.
39
+ * Benchmark script is improved to take some command-line options.
40
+ * Document fixed.
41
+
42
+
43
+ Release 1.0.1 (2015-12-06)
44
+ --------------------------
45
+
46
+ * Fix document
47
+
48
+
49
+ Release 1.0.0 (2015-12-06)
50
+ --------------------------
51
+
52
+ * First release
data/MIT-LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- $Copyright: copyright(c) 2015 kuwata-lab.com all rights reserved $
3
+ $Copyright: copyright(c) 2015 kwatch@gmail.com $
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Rack::JetRouter
2
2
 
3
- ($Release: 1.2.0 $)
3
+ ($Release: 1.3.0 $)
4
4
 
5
5
  Rack::JetRouter is crazy-fast router library for Rack application,
6
6
  derived from [Keight.rb](https://github.com/kwatch/keight/tree/ruby).
7
7
 
8
- Rack::JetRouter requires Ruby >= 2.0.
8
+ Rack::JetRouter requires Ruby >= 2.4.
9
9
 
10
10
 
11
11
  ## Benchmark
@@ -14,45 +14,42 @@ Benchmark script is [here](https://github.com/kwatch/rack-jet_router/blob/releas
14
14
 
15
15
  | Name | Version |
16
16
  | ------------------ | ------- |
17
- | Ruby | 2.3.1 |
18
- | Rack | 1.6.4 |
19
- | Rack::JetRouter | 1.2.0 |
17
+ | Ruby | 3.2.2 |
18
+ | Rack | 2.2.8 |
19
+ | Rack::JetRouter | 1.3.0 |
20
20
  | Rack::Multiplexer | 0.0.8 |
21
- | Sinatra | 1.4.6 |
22
- | Keight.rb | 0.3.0 |
23
- | Hanami | 0.8.0 |
21
+ | Sinatra | 3.1.0 |
22
+ | Keight.rb | 1.0.0 |
23
+ | Hanami::Router | 2.0.2 |
24
24
 
25
- (Macbook Air, Intel Core i7 1.7GHz, OS X EL Capitan)
25
+ (Macbook Pro, Apple M1 Pro, macOS Ventura 13.6.2)
26
26
 
27
27
 
28
28
  ### JetRouter vs. Rack vs. Sinatra vs. Keight.rb vs. Hanami:
29
29
 
30
30
  ```
31
- ## Ranking real
32
- (Rack plain) /api/aaa01 0.9316 (100.0%) ********************
33
- (Rack plain) /api/aaa01/123 1.0222 ( 91.1%) ******************
34
- (JetRouter) /api/aaa01 1.4191 ( 65.6%) *************
35
- (JetRouter) /api/aaa01/123 6.0146 ( 15.5%) ***
36
- (Multiplexer) /api/aaa01 6.1026 ( 15.3%) ***
37
- (Keight.rb) /api/aaa01 7.2330 ( 12.9%) ***
38
- (R::Req+Res) /api/aaa01 10.7835 ( 8.6%) **
39
- (R::Req+Res) /api/aaa01/123 10.8412 ( 8.6%) **
40
- (Keight.rb) /api/aaa01/123 10.8708 ( 8.6%) **
41
- (Hanami::Router) /api/zzz26 11.5185 ( 8.1%) **
42
- (Hanami::Router) /api/aaa01 11.7033 ( 8.0%) **
43
- (Hanami::Router) /api/aaa01/123 17.9229 ( 5.2%) *
44
- (Multiplexer) /api/aaa01/123 18.6987 ( 5.0%) *
45
- (Sinatra) /api/aaa01 109.7597 ( 0.8%)
46
- (Sinatra) /api/aaa01/123 121.3258 ( 0.8%)
31
+ ## Ranking usec/req Graph (longer=faster)
32
+ (JetRouter) /api/aaa01 0.2816 (100.0%) ********************
33
+ (Multiplexer) /api/aaa01 1.2586 ( 22.4%) ****
34
+ (Hanami::Router) /api/aaa01 1.3296 ( 21.2%) ****
35
+ (JetRouter) /api/aaa01/123 1.5861 ( 17.8%) ****
36
+ (Rack::Req+Res) /api/aaa01/123 1.7369 ( 16.2%) ***
37
+ (Rack::Req+Res) /api/aaa01 1.7438 ( 16.1%) ***
38
+ (Keight) /api/aaa01 1.8906 ( 14.9%) ***
39
+ (Keight) /api/aaa01/123 2.8998 ( 9.7%) **
40
+ (Multiplexer) /api/aaa01/123 2.9166 ( 9.7%) **
41
+ (Hanami::Router) /api/aaa01/123 4.0996 ( 6.9%) *
42
+ (Sinatra) /api/aaa01 49.6862 ( 0.6%)
43
+ (Sinatra) /api/aaa01/123 54.3448 ( 0.5%)
47
44
  ```
48
45
 
49
46
  * If URL path has no path parameter (such as `/api/hello`),
50
- Rack::JetRouter is a litte shower than plain Rack application.
47
+ JetRouter is significantly fast.
51
48
  * If URL path contains path parameter (such as `/api/hello/:id`),
52
- Rack::JetRouter becomes slower, but it is enough small (about 6usec/req).
53
- * Overhead of Rack::JetRouter is smaller than that of Rack::Reqeuast +
49
+ JetRouter becomes slower, but it is enough small (about 1.3 usec/req).
50
+ * Overhead of JetRouter is smaller than that of Rack::Reqeuast +
54
51
  Rack::Response.
55
- * Hanami is a litte slow.
52
+ * Hanami is slower than JetRouter, but quite enough fast.
56
53
  * Sinatra is too slow.
57
54
 
58
55
 
@@ -60,20 +57,37 @@ Benchmark script is [here](https://github.com/kwatch/rack-jet_router/blob/releas
60
57
 
61
58
  ```
62
59
  ## Ranking usec/req Graph (longer=faster)
63
- (JetRouter) /api/aaa01 1.4191 ( 65.6%) *************
64
- (JetRouter) /api/zzz26 1.4300 ( 65.1%) *************
65
- (JetRouter) /api/aaa01/123 6.0146 ( 15.5%) ***
66
- (Multiplexer) /api/aaa01 6.1026 ( 15.3%) ***
67
- (JetRouter) /api/zzz26/789 6.9102 ( 13.5%) ***
68
- (Multiplexer) /api/aaa01/123 18.6987 ( 5.0%) *
69
- (Multiplexer) /api/zzz26 30.7618 ( 3.0%) *
70
- (Multiplexer) /api/zzz26/789 42.6660 ( 2.2%)
60
+ (JetRouter) /api/aaa01 0.2816 (100.0%) ********************
61
+ (JetRouter) /api/zzz26 0.2823 ( 99.7%) ********************
62
+ (Multiplexer) /api/aaa01 1.2586 ( 22.4%) ****
63
+ (JetRouter) /api/aaa01/123 1.5861 ( 17.8%) ****
64
+ (Multiplexer) /api/aaa01/123 2.9166 ( 9.7%) **
65
+ (JetRouter) /api/zzz26/456 3.5767 ( 7.9%) **
66
+ (Multiplexer) /api/zzz26 14.8423 ( 1.9%)
67
+ (Multiplexer) /api/zzz26/456 16.8930 ( 1.7%)
71
68
  ```
72
69
 
73
70
  * JetRouter is about 4~6 times faster than Rack::Multiplexer.
74
71
  * Rack::Multiplexer is getting worse in promotion to the number of URL paths.
75
72
 
76
73
 
74
+ ### JetRouter vs. Hanami::Router
75
+
76
+ ```
77
+ ## Ranking usec/req Graph (longer=faster)
78
+ (JetRouter) /api/aaa01 0.2816 (100.0%) ********************
79
+ (JetRouter) /api/zzz26 0.2823 ( 99.7%) ********************
80
+ (Hanami::Router) /api/zzz26 1.3280 ( 21.2%) ****
81
+ (Hanami::Router) /api/aaa01 1.3296 ( 21.2%) ****
82
+ (JetRouter) /api/aaa01/123 1.5861 ( 17.8%) ****
83
+ (JetRouter) /api/zzz26/456 3.5767 ( 7.9%) **
84
+ (Hanami::Router) /api/zzz26/456 4.0898 ( 6.9%) *
85
+ (Hanami::Router) /api/aaa01/123 4.0996 ( 6.9%) *
86
+ ```
87
+
88
+ * Hanami is slower than JetRouter, but it has enough speed.
89
+
90
+
77
91
  ## Examples
78
92
 
79
93
  ### #1: Depends only on Request Path
@@ -189,6 +203,69 @@ handler.__send__(action, args)
189
203
  ## Topics
190
204
 
191
205
 
206
+ ### Nested Array v.s. Nested Hash
207
+
208
+ URL path mapping can be not only nested Array but also nested Hash.
209
+
210
+ ```ruby
211
+ ## nested Array
212
+ mapping = [
213
+ ["/api", [
214
+ ["/books", [
215
+ ["" , book_list_api],
216
+ ["/:id" , book_show_api],
217
+ ]],
218
+ ]],
219
+ ]
220
+
221
+ ## nested Hash
222
+ mapping = {
223
+ "/api" => {
224
+ "/books" => {
225
+ "" => book_list_api,
226
+ "/:id" => book_show_api,
227
+ },
228
+ },
229
+ }
230
+ ```
231
+
232
+ But nested Hash mapping can't include request method mappings, because
233
+ it is hard to distinguish between URL path mapping and request method mapping.
234
+
235
+ ```ruby
236
+ ## NOT OK
237
+ mapping = {
238
+ "/api" => {
239
+ "/books" => {
240
+ "" => {GET: book_list_api, POST: book_create_api},
241
+ "/:id" => {GET: book_show_api, PUT: book_update_api},
242
+ },
243
+ },
244
+ }
245
+ ```
246
+
247
+ In this case, define subclass of Hash class and use it instead of Hash.
248
+
249
+ ```ruby
250
+ class Map < Hash # define subclass of Hash class
251
+ end
252
+
253
+ def Map(**kwargs) # helper method to create subclass object
254
+ return Map.new.update(kwargs)
255
+ end
256
+
257
+ ## OK
258
+ mapping = {
259
+ "/api" => {
260
+ "/books" => {
261
+ "" => Map(GET: book_list_api, POST: book_create_api),
262
+ "/:id" => Map(GET: book_show_api, PUT: book_update_api),
263
+ },
264
+ },
265
+ }
266
+ ```
267
+
268
+
192
269
  ### URL Path Parameters
193
270
 
194
271
  In Rack application, URL path parameters (such as `{"id"=>"123"}`) are
@@ -201,13 +278,19 @@ BookApp = proc {|env|
201
278
  }
202
279
  ```
203
280
 
281
+ Key name can be changed by ``env_key:`` keyword argument of ``JetRouter.new()``.
282
+
283
+ ```ruby
284
+ router = Rack::JetRouter.new(mapping, env_key: "rack.urlpath_params")
285
+ ```
286
+
204
287
  If you want to tweak URL path parameters, define subclass of Rack::JetRouter
205
- and override `#build_urlpath_parameter_vars(env, vars)`.
288
+ and override `#build_param_values(names, values)`.
206
289
 
207
290
  ```ruby
208
291
  class MyRouter < JetRouter
209
292
 
210
- def build_urlpath_parameter_vars(names, values)
293
+ def build_param_values(names, values)
211
294
  return names.zip(values).each_with_object({}) {|(k, v), d|
212
295
  ## converts urlpath pavam value into integer
213
296
  v = v.to_i if k == 'id' || k.end_with?('_id')
@@ -219,7 +302,70 @@ end
219
302
  ```
220
303
 
221
304
 
222
- ### Auto-redirection.
305
+ ### Integer Type Parameters
306
+
307
+ Keyword argument ``int_param:`` of ``JetRouter.new()`` specifies
308
+ parameter name pattern (regexp) to treat as integer type.
309
+ For example, ``int_param: /(?:\A|_)id\z/`` treats ``id`` or ``xxx_id``
310
+ parameter values as integer type.
311
+
312
+ ```ruby
313
+ require 'rack'
314
+ require 'rack/jet_router'
315
+
316
+ rack_app = proc {|env|
317
+ params = env['rack.urlpath_params']
318
+ type = params["book_id"].class
319
+ text = "params=#{params.inspect}, type=#{type}"
320
+ [200, {}, [text]]
321
+ }
322
+
323
+ mapping = [
324
+ ["/api/books/:book_id", rack_app]
325
+ ]
326
+ router = Rack::JetRouter.new(mapping, int_param: /(?:\A|_)id\z/
327
+
328
+ env = Rack::MockRequest.env_for("/api/books/123")
329
+ tuple = router.call(env)
330
+ puts tuple[2] #=> params={"book_id"=>123}, type=Integer
331
+ ```
332
+
333
+ Integer type parameters match to only integers.
334
+
335
+ ```ruby
336
+ env = Rack::MockRequest.env_for("/api/books/FooBar")
337
+ tuple = router.call(env)
338
+ puts tuple[2] #=> 404 Not Found
339
+ ```
340
+
341
+
342
+ <!--
343
+
344
+ ### URL Path Multiple Extension
345
+
346
+ It is available to specify multiple extension of URL path.
347
+
348
+ ```ruby
349
+ mapping = {
350
+ "/api/books" => {
351
+ "/:id(.html|.json)" => book_api,
352
+ },
353
+ }
354
+ ```
355
+
356
+ In above example, the following URL path patterns are enabled.
357
+
358
+ * ``/api/books/:id``
359
+ * ``/api/books/:id.html``
360
+ * ``/api/books/:id.json``
361
+
362
+ Notice that ``env['rack.urlpath_params']['format']`` is not set
363
+ because ``:format`` is not specified in URL path pattern.
364
+
365
+ -->
366
+
367
+
368
+ ### Auto-redirection
223
369
 
224
370
  Rack::JetRouter implements auto-redirection.
225
371
 
@@ -281,42 +427,6 @@ Above methods are invoked from `Rack::JetRouter#call()`.
281
427
 
282
428
  ## Copyright and License
283
429
 
284
- $Copyright: copyright(c) 2015-2016 kuwata-lab.com all rights reserved $
430
+ $Copyright: copyright(c) 2015 kwatch@gmail.com $
285
431
 
286
432
  $License: MIT License $
287
-
288
-
289
- ## History
290
-
291
-
292
- ### 2016-10-16: Release 1.2.0
293
-
294
- * Change auto-redirection to be occurred only on GET or HEAD methods.
295
- * Code is rewrited, especially around `Rack::JetRouter#compile_mapping()`.
296
- * Update benchmark script to support `Hanabi::Router`.
297
-
298
-
299
- ### 2015-12-29: Release 1.1.1
300
-
301
- * Fix benchmark script.
302
- * Fix document.
303
-
304
-
305
- ### 2015-12-28: Release 1.1.0
306
-
307
- * **NOTICE** `Rack::JetRouter#find()` is renamed to `#lookup()`.<br>
308
- `#find()` is also available for compatibility, but not recommended.
309
- * Performance improved when number of URL path parameter is 1.
310
- * Regular expression generated is improved.
311
- * Benchmark script is improved to take some command-line options.
312
- * Document fixed.
313
-
314
-
315
- ### 2015-12-06: Release 1.0.1
316
-
317
- * Fix document
318
-
319
-
320
- ### 2015-12-06: Release 1.0.0
321
-
322
- * First release
data/bench/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rack"
6
+ gem "sinatra"
7
+ gem "rack-jet_router"
8
+ gem "rack-multiplexer"
9
+ gem "keight"
10
+ #gem "hanami"
11
+ gem "hanami-router"
12
+
13
+ gem "benchmarker"
data/bench/Rakefile.rb ADDED
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+
5
+ desc "run 'bench.rb' script"
6
+ task :bench, :N do |t, args|
7
+ n = args[:N] || 1000000
8
+ ruby "bench.rb", "--N=#{n}"
9
+ #ruby "bench.rb", "--N=#{n}", "--sinatra=0", "--multiplexer=0"
10
+ #ruby "bench.rb", "--N=#{n}", "--rack=0", "--jetrouter=0", "--keight=0", "--multiplexer=0", "--sinatra=0", "--hanami=0"
11
+ end