rack-jet_router 1.1.1 → 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: 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