rack-jet_router 1.1.1 → 1.3.0

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: c763fbc224d9c9c21718bf685203b35694c20f3b
4
- data.tar.gz: 56bc71a1d83180f2970f1d95985fc8b2fa9b91bc
2
+ SHA256:
3
+ metadata.gz: ffb2322f3ac227a3d07fa95c120d25c3dcb8763f9ea925be7a3a03df11c00ba9
4
+ data.tar.gz: 60b292dd4a1307a2fd1cbfcb474746131599fe0ba0ae93768b40f2cf0c9e5fa5
5
5
  SHA512:
6
- metadata.gz: b72f539eb7750a754daea1189aa0035e8010a93d7debf74ef7f6a4b927223daf19f4bfbf0165192aab08c0e395289fabc423ee4690e6ab0ff0417603185334f1
7
- data.tar.gz: 565dcf52b9c34e81803474de3c212f2b2b92d543a85057f3ab7959764f724b1ea2a5dc07c11caa4aca06a79aa318410000dabb98001ef4e0cbad4aaaa711fe11
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,39 +1,55 @@
1
1
  # Rack::JetRouter
2
2
 
3
- ($Release: 1.1.1 $)
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
12
12
 
13
- Benchmark script is [here](https://github.com/kwatch/rack-jet_router/blob/dev/bench/bench.rb).
13
+ Benchmark script is [here](https://github.com/kwatch/rack-jet_router/blob/release/bench/bench.rb).
14
14
 
15
- ### JetRouter vs. Rack vs. Sinatra vs. Keight.rb:
15
+ | Name | Version |
16
+ | ------------------ | ------- |
17
+ | Ruby | 3.2.2 |
18
+ | Rack | 2.2.8 |
19
+ | Rack::JetRouter | 1.3.0 |
20
+ | Rack::Multiplexer | 0.0.8 |
21
+ | Sinatra | 3.1.0 |
22
+ | Keight.rb | 1.0.0 |
23
+ | Hanami::Router | 2.0.2 |
24
+
25
+ (Macbook Pro, Apple M1 Pro, macOS Ventura 13.6.2)
26
+
27
+
28
+ ### JetRouter vs. Rack vs. Sinatra vs. Keight.rb vs. Hanami:
16
29
 
17
30
  ```
18
31
  ## Ranking usec/req Graph (longer=faster)
19
- (Rack plain) /api/aaa01 1.0619 ***************
20
- (Rack plain) /api/aaa01/123 0.8729 ******************
21
- (R::Req+Res) /api/aaa01 9.5361 **
22
- (R::Req+Res) /api/aaa01/123 9.5321 **
23
- (JetRouter) /api/aaa01 1.3231 ************
24
- (JetRouter) /api/aaa01/123 5.9796 ***
25
- (Keight.rb) /api/aaa01 6.4314 **
26
- (Keight.rb) /api/aaa01/123 10.2339 **
27
- (Sinatra) /api/aaa01 104.7575
28
- (Sinatra) /api/aaa01/123 115.8220
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%)
29
44
  ```
30
45
 
31
46
  * If URL path has no path parameter (such as `/api/hello`),
32
- Rack::JetRouter is a litte shower than plain Rack application.
47
+ JetRouter is significantly fast.
33
48
  * If URL path contains path parameter (such as `/api/hello/:id`),
34
- Rack::JetRouter becomes slower, but it is enough small (about 6usec/req).
35
- * 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 +
36
51
  Rack::Response.
52
+ * Hanami is slower than JetRouter, but quite enough fast.
37
53
  * Sinatra is too slow.
38
54
 
39
55
 
@@ -41,17 +57,35 @@ Benchmark script is [here](https://github.com/kwatch/rack-jet_router/blob/dev/be
41
57
 
42
58
  ```
43
59
  ## Ranking usec/req Graph (longer=faster)
44
- (JetRouter) /api/aaa01 1.3231 ************
45
- (JetRouter) /api/aaa01/123 5.9796 ***
46
- (JetRouter) /api/zzz26 1.4089 ***********
47
- (JetRouter) /api/zzz26/789 6.5142 **
48
- (Multiplexer) /api/aaa01 5.9073 ***
49
- (Multiplexer) /api/aaa01/123 18.2102 *
50
- (Multiplexer) /api/zzz26 24.4013 *
51
- (Multiplexer) /api/zzz26/789 36.1558
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%)
52
68
  ```
53
69
 
54
- * JetRouter is about 3~5 times faster than Rack::Multiplexer.
70
+ * JetRouter is about 4~6 times faster than Rack::Multiplexer.
71
+ * Rack::Multiplexer is getting worse in promotion to the number of URL paths.
72
+
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.
55
89
 
56
90
 
57
91
  ## Examples
@@ -169,6 +203,69 @@ handler.__send__(action, args)
169
203
  ## Topics
170
204
 
171
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
+
172
269
  ### URL Path Parameters
173
270
 
174
271
  In Rack application, URL path parameters (such as `{"id"=>"123"}`) are
@@ -181,13 +278,19 @@ BookApp = proc {|env|
181
278
  }
182
279
  ```
183
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
+
184
287
  If you want to tweak URL path parameters, define subclass of Rack::JetRouter
185
- and override `#build_urlpath_parameter_vars(env, vars)`.
288
+ and override `#build_param_values(names, values)`.
186
289
 
187
290
  ```ruby
188
291
  class MyRouter < JetRouter
189
292
 
190
- def build_urlpath_parameter_vars(names, values)
293
+ def build_param_values(names, values)
191
294
  return names.zip(values).each_with_object({}) {|(k, v), d|
192
295
  ## converts urlpath pavam value into integer
193
296
  v = v.to_i if k == 'id' || k.end_with?('_id')
@@ -199,6 +302,81 @@ end
199
302
  ```
200
303
 
201
304
 
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
369
+
370
+ Rack::JetRouter implements auto-redirection.
371
+
372
+ * When `/foo` is provided and `/foo/` is requested, then Rack::JetRouter redirects to `/foo` automatically.
373
+ * When `/foo/` is provided and `/foo` is requested, then Rack::JetRouter redirects to `/foo/` automatically.
374
+
375
+ Notice that auto-redirection is occurred only on `GET` or `HEAD` methods, because
376
+ browser cannot handle redirection on `POST`, `PUT`, and `DELETE` methods correctly.
377
+ Don't depend on auto-redirection feature so much.
378
+
379
+
202
380
  ### Variable URL Path Cache
203
381
 
204
382
  It is useful to classify URL path patterns into two types: fixed and variable.
@@ -249,29 +427,6 @@ Above methods are invoked from `Rack::JetRouter#call()`.
249
427
 
250
428
  ## Copyright and License
251
429
 
252
- $Copyright: copyright(c) 2015 kuwata-lab.com all rights reserved $
430
+ $Copyright: copyright(c) 2015 kwatch@gmail.com $
253
431
 
254
432
  $License: MIT License $
255
-
256
-
257
- ## History
258
-
259
-
260
- ### 2015-12-28: Release 1.1.0
261
-
262
- * **NOTICE** `Rack::JetRouter#find()` is renamed to `#lookup()`.<br>
263
- `#find()` is also available for compatibility, but not recommended.
264
- * Performance improved when number of URL path parameter is 1.
265
- * Regular expression generated is improved.
266
- * Benchmark script is improved to take some command-line options.
267
- * Document fixed.
268
-
269
-
270
- ### 2015-12-06: Release 1.0.1
271
-
272
- * Fix document
273
-
274
-
275
- ### 2015-12-06: Release 1.0.0
276
-
277
- * 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