rack-jet_router 1.2.0 → 1.3.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
- SHA1:
3
- metadata.gz: dbed04ca4adfdce5a3e82234dd6182e18519dc62
4
- data.tar.gz: bdec9db77792ffba5bca3e05ae4bf62f35cbf555
2
+ SHA256:
3
+ metadata.gz: 55c3dc8f5747e61e864ee478f7336d755dc022cb4ebc2f75baeae2b2f1059bd8
4
+ data.tar.gz: '085324025413ff2d565f6aad7d8fc1827486d9454772f3c745fb1bd3f3d575f3'
5
5
  SHA512:
6
- metadata.gz: 0d90ffbb230351b7f0054d7d382b377dca41832cbfe2a47d6793c0ac88dbc075104535bf4529a6e1c50251365faadefb8d1fa02342d7104420cd8eb6316ea495
7
- data.tar.gz: af141052683402fd8dedc4538b548bab59c816714e423236fe83cd70d2865f77337f5c6b9e0d93380e49fe4547995e36f256943be6426a20b1d04a82cfe69697
6
+ metadata.gz: 357cfa2babfeb364ff8ca485247eed0f1cb9f7a0c5d7c5ff7c907d593d488bb3e365e198cb6eaf89328b7f85c3e349e273793ade17ee1e94822eed139df90bd0
7
+ data.tar.gz: a6bb2a5d973fa092f356b733ce4ca5f1af335ec53f7d83f9087e0dec271ada489ae80576ba71a4199dd084a6ffc3a25e74e6c29d8e2a1ff0c0e535e2fcf83e8e
data/CHANGES.md ADDED
@@ -0,0 +1,58 @@
1
+ CHANGES
2
+ =======
3
+
4
+
5
+ Release 1.3.1 (2023-12-10)
6
+ --------------------------
7
+
8
+ * [bugfix] Fixed to correctly handle suffixed URL path pattern such as `/foo(.:format)`.
9
+
10
+
11
+ Release 1.3.0 (2023-12-09)
12
+ --------------------------
13
+
14
+ * [enhance] Performance has improved (about 10%). This improvement was achieved by optimizing regular expressions.
15
+ * [enhance] URL path mapping can be nested Hash as well as nested Array. See the document for detail.
16
+ * [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.
17
+ * [enhance] Passing the `env_key:` keyword argument to `JetRouter.new()` changes the key of environemnt to store URL path parameter values.
18
+ * [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.
19
+ * [change] Rename `JetRouter#build_urlpath_parameter_vars()` to `JetRouter#build_param_values()`.
20
+ * [change] Update benchmark script to require 'benchmarker' gem.
21
+
22
+
23
+ Release 1.2.0 (2016-10-16)
24
+ --------------------------
25
+
26
+ * Change auto-redirection to be occurred only on GET or HEAD methods.
27
+ * Code is rewrited, especially around `Rack::JetRouter#compile_mapping()`.
28
+ * Update benchmark script to support `Hanabi::Router`.
29
+
30
+
31
+ Release 1.1.1 (2015-12-29)
32
+ --------------------------
33
+
34
+ * Fix benchmark script.
35
+ * Fix document.
36
+
37
+
38
+ Release 1.1.0 (2015-12-28)
39
+ --------------------------
40
+
41
+ * **NOTICE** `Rack::JetRouter#find()` is renamed to `#lookup()`.
42
+ `#find()` is also available for compatibility, but not recommended.
43
+ * Performance improved when number of URL path parameter is 1.
44
+ * Regular expression generated is improved.
45
+ * Benchmark script is improved to take some command-line options.
46
+ * Document fixed.
47
+
48
+
49
+ Release 1.0.1 (2015-12-06)
50
+ --------------------------
51
+
52
+ * Fix document
53
+
54
+
55
+ Release 1.0.0 (2015-12-06)
56
+ --------------------------
57
+
58
+ * 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.1 $)
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