rack-jet_router 1.3.1 → 1.4.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 +4 -4
- data/CHANGES.md +10 -0
- data/README.md +80 -72
- data/bench/Gemfile +5 -4
- data/bench/Rakefile.rb +3 -3
- data/bench/bench.rb +330 -244
- data/lib/rack/jet_router.rb +119 -62
- data/rack-jet_router.gemspec +1 -1
- data/test/builder_test.rb +129 -41
- data/test/router_test.rb +49 -7
- data/test/shared.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f8d5e69ec9a40e0698eb97d91f28882b9398f19ec85d2a412a5e79c86efc8fe
|
4
|
+
data.tar.gz: 6d7f33be397ffe163fbe4ac87e050213c7f05fdef37adfc3a1189ccb2861d608
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1685c663f0116bb2e6953bdd47f4bfa2976c9fd38b24f12e973b0893d16b307f67a5416fd6e7718650449f4a745a4f3b8cb33ff6d00e1e9c103c211a54cc9f7d
|
7
|
+
data.tar.gz: e0a8e23518ad123315c562f83b393df77caf06f680a349a5bf9303e4e05b0c239a16dd2500752d15c4aa6899c4f0d846753673cadd2b82f0e257ca00ef25c2df
|
data/CHANGES.md
CHANGED
@@ -2,6 +2,16 @@ CHANGES
|
|
2
2
|
=======
|
3
3
|
|
4
4
|
|
5
|
+
Release 1.4.0 (2024-01-02)
|
6
|
+
--------------------------
|
7
|
+
|
8
|
+
* [enhance] Supports '*file' style path parameter.
|
9
|
+
* [enhance] Allows to use mormal Hash object as request method mapping.
|
10
|
+
* [enhance] Supports `(.html|.json)` style pattern.
|
11
|
+
* [enhance] Treats `/foo(.html|.json)` as three fixed paths `/foo`, `/foo.html` and `/foo.json`. This is much faster than `/foo(.:format)`.
|
12
|
+
* [enhance] Rewrite benchmark script.
|
13
|
+
|
14
|
+
|
5
15
|
Release 1.3.1 (2023-12-10)
|
6
16
|
--------------------------
|
7
17
|
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Rack::JetRouter
|
2
2
|
|
3
|
-
($Release: 1.
|
3
|
+
($Release: 1.4.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).
|
@@ -93,30 +93,29 @@ Benchmark script is [here](https://github.com/kwatch/rack-jet_router/blob/releas
|
|
93
93
|
### #1: Depends only on Request Path
|
94
94
|
|
95
95
|
```ruby
|
96
|
-
# -*- coding: utf-8 -*-
|
97
|
-
|
98
96
|
require 'rack'
|
99
97
|
require 'rack/jet_router'
|
100
98
|
|
101
99
|
## Assume that welcome_app, books_api, ... are Rack application.
|
102
|
-
mapping =
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
100
|
+
mapping = {
|
101
|
+
"/" => welcome_app,
|
102
|
+
"/api" => {
|
103
|
+
"/books" => {
|
104
|
+
"" => books_api,
|
105
|
+
"/:id(.:format)" => book_api,
|
106
|
+
"/:book_id/comments/:comment_id" => comment_api,
|
107
|
+
},
|
108
|
+
},
|
109
|
+
"/admin" => {
|
110
|
+
"/books" => admin_books_app,
|
111
|
+
},
|
112
|
+
}
|
115
113
|
|
116
114
|
router = Rack::JetRouter.new(mapping)
|
117
115
|
p router.lookup('/api/books/123.json')
|
118
116
|
#=> [book_api, {"id"=>"123", "format"=>"json"}]
|
119
117
|
|
118
|
+
env = Rack::MockRequest.env_for("/api/books/123.json", method: 'GET')
|
120
119
|
status, headers, body = router.call(env)
|
121
120
|
```
|
122
121
|
|
@@ -124,30 +123,29 @@ status, headers, body = router.call(env)
|
|
124
123
|
### #2: Depends on both Request Path and Method
|
125
124
|
|
126
125
|
```ruby
|
127
|
-
# -*- coding: utf-8 -*-
|
128
|
-
|
129
126
|
require 'rack'
|
130
127
|
require 'rack/jet_router'
|
131
128
|
|
132
129
|
## Assume that welcome_app, book_list_api, ... are Rack application.
|
133
|
-
mapping =
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
130
|
+
mapping = {
|
131
|
+
"/" => {GET: welcome_app}, # not {"GET"=>...}
|
132
|
+
"/api" => {
|
133
|
+
"/books" => { # not {"GET"=>..., "POST"=>...}
|
134
|
+
"" => {GET: book_list_api, POST: book_create_api},
|
135
|
+
"/:id(.:format)" => {GET: book_show_api, PUT: book_update_api},
|
136
|
+
"/:book_id/comments/:comment_id" => {POST: comment_create_api},
|
137
|
+
},
|
138
|
+
},
|
139
|
+
"/admin" => {
|
140
|
+
"/books" => {ANY: admin_books_app}, # not {"ANY"=>...}
|
141
|
+
},
|
142
|
+
}
|
146
143
|
|
147
144
|
router = Rack::JetRouter.new(mapping)
|
148
145
|
p router.lookup('/api/books/123')
|
149
146
|
#=> [{"GET"=>book_show_api, "PUT"=>book_update_api}, {"id"=>"123", "format"=>nil}]
|
150
147
|
|
148
|
+
env = Rack::MockRequest.env_for("/api/books/123", method: 'GET')
|
151
149
|
status, headers, body = router.call(env)
|
152
150
|
```
|
153
151
|
|
@@ -158,8 +156,6 @@ automatically when passing to `Rack::JetRouter.new()`.
|
|
158
156
|
### #3: RESTful Framework
|
159
157
|
|
160
158
|
```ruby
|
161
|
-
# -*- coding: utf-8 -*-
|
162
|
-
|
163
159
|
require 'rack'
|
164
160
|
require 'rack/jet_router'
|
165
161
|
|
@@ -179,33 +175,33 @@ class BooksAPI < API
|
|
179
175
|
def delete(id: nil); ....; end
|
180
176
|
end
|
181
177
|
|
182
|
-
mapping =
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
POST: [BooksAPI, :create]}
|
187
|
-
|
178
|
+
mapping = {
|
179
|
+
"/api" => {
|
180
|
+
"/books" => { # not {"GET"=>..., "POST"=>...}
|
181
|
+
"" => {GET: [BooksAPI, :index],
|
182
|
+
POST: [BooksAPI, :create]},
|
183
|
+
"/:id" => {GET: [BooksAPI, :show],
|
188
184
|
PUT: [BooksAPI, :update],
|
189
|
-
DELETE: [BooksAPI, :delete]}
|
190
|
-
|
191
|
-
|
192
|
-
|
185
|
+
DELETE: [BooksAPI, :delete]},
|
186
|
+
},
|
187
|
+
},
|
188
|
+
}
|
193
189
|
router = Rack::JetRouter.new(mapping)
|
194
|
-
dict, args = router.lookup(
|
190
|
+
dict, args = router.lookup("/api/books/123")
|
195
191
|
p dict #=> {"GET"=>[BooksAPI, :show], "PUT"=>[...], "DELETE"=>[...]}
|
196
192
|
p args #=> {"id"=>"123"}
|
197
|
-
klass,
|
193
|
+
klass, method_name = dict["GET"]
|
198
194
|
handler = klass.new(Rack::Request.new(env), Rack::Response.new)
|
199
|
-
handler.__send__(
|
195
|
+
handler.__send__(method_name, args)
|
200
196
|
```
|
201
197
|
|
202
198
|
|
203
199
|
## Topics
|
204
200
|
|
205
201
|
|
206
|
-
### Nested
|
202
|
+
### Nested Hash v.s. Nested Array
|
207
203
|
|
208
|
-
URL path mapping can be not only nested
|
204
|
+
URL path mapping can be not only nested Hash but also nested Array.
|
209
205
|
|
210
206
|
```ruby
|
211
207
|
## nested Array
|
@@ -229,11 +225,12 @@ mapping = {
|
|
229
225
|
}
|
230
226
|
```
|
231
227
|
|
232
|
-
|
233
|
-
|
228
|
+
When using nested Hash, request method mappings should be ``{GET: ...}``
|
229
|
+
instead of ``{"GET"=>...}``, because with the latter it is hard to
|
230
|
+
distinguish between URL path mapping and request method mapping.
|
234
231
|
|
235
232
|
```ruby
|
236
|
-
##
|
233
|
+
## OK
|
237
234
|
mapping = {
|
238
235
|
"/api" => {
|
239
236
|
"/books" => {
|
@@ -242,24 +239,13 @@ mapping = {
|
|
242
239
|
},
|
243
240
|
},
|
244
241
|
}
|
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
242
|
|
253
|
-
|
254
|
-
return Map.new.update(kwargs)
|
255
|
-
end
|
256
|
-
|
257
|
-
## OK
|
243
|
+
## Not OK
|
258
244
|
mapping = {
|
259
245
|
"/api" => {
|
260
246
|
"/books" => {
|
261
|
-
"" =>
|
262
|
-
"/:id" =>
|
247
|
+
"" => {"GET"=>book_list_api, "POST"=>book_create_api},
|
248
|
+
"/:id" => {"GET"=>book_show_api, "PUT"=>book_update_api},
|
263
249
|
},
|
264
250
|
},
|
265
251
|
}
|
@@ -302,6 +288,32 @@ end
|
|
302
288
|
```
|
303
289
|
|
304
290
|
|
291
|
+
### File Path Type Parameters
|
292
|
+
|
293
|
+
If path parameter is ``*foo`` instead of ``:foo``, that parameter matches to any path.
|
294
|
+
|
295
|
+
```ruby
|
296
|
+
## Assume that book_api and staticfile_app are Rack application.
|
297
|
+
mapping = {
|
298
|
+
"/api" => {
|
299
|
+
"/books" => {
|
300
|
+
"/:id" => book_api,
|
301
|
+
},
|
302
|
+
},
|
303
|
+
"/static/*filepath" => staticfile_app, # !!!
|
304
|
+
}
|
305
|
+
|
306
|
+
router = Rack::JetRouter.new(mapping)
|
307
|
+
app, args = router.lookup("/static/images/logo.png") # !!!
|
308
|
+
p app #=> staticfile_app
|
309
|
+
p args #=> {"filepath"=>"images/logo.png"}
|
310
|
+
```
|
311
|
+
|
312
|
+
``*foo`` should be at end of the URL path.
|
313
|
+
For example, ``/static/*filepath`` is OK, while ``"/static/*filepath.html"``
|
314
|
+
or ``"/static/(*filepath)"`` raises error.
|
315
|
+
|
316
|
+
|
305
317
|
### Integer Type Parameters
|
306
318
|
|
307
319
|
Keyword argument ``int_param:`` of ``JetRouter.new()`` specifies
|
@@ -320,9 +332,9 @@ rack_app = proc {|env|
|
|
320
332
|
[200, {}, [text]]
|
321
333
|
}
|
322
334
|
|
323
|
-
mapping =
|
324
|
-
|
325
|
-
|
335
|
+
mapping = {
|
336
|
+
"/api/books/:book_id" => rack_app,
|
337
|
+
}
|
326
338
|
router = Rack::JetRouter.new(mapping, int_param: /(?:\A|_)id\z/
|
327
339
|
|
328
340
|
env = Rack::MockRequest.env_for("/api/books/123")
|
@@ -339,8 +351,6 @@ puts tuple[2] #=> 404 Not Found
|
|
339
351
|
```
|
340
352
|
|
341
353
|
|
342
|
-
<!--
|
343
|
-
|
344
354
|
### URL Path Multiple Extension
|
345
355
|
|
346
356
|
It is available to specify multiple extension of URL path.
|
@@ -362,8 +372,6 @@ In above example, the following URL path patterns are enabled.
|
|
362
372
|
Notice that ``env['rack.urlpath_params']['format']`` is not set
|
363
373
|
because ``:format`` is not specified in URL path pattern.
|
364
374
|
|
365
|
-
-->
|
366
|
-
|
367
375
|
|
368
376
|
### Auto-redirection
|
369
377
|
|
data/bench/Gemfile
CHANGED
@@ -2,12 +2,13 @@
|
|
2
2
|
|
3
3
|
source "https://rubygems.org"
|
4
4
|
|
5
|
+
gem "benchmarker"
|
6
|
+
|
5
7
|
gem "rack"
|
6
|
-
gem "
|
8
|
+
#gem "rocketrouter"
|
7
9
|
gem "rack-jet_router"
|
8
|
-
gem "rack-multiplexer"
|
9
10
|
gem "keight"
|
10
11
|
#gem "hanami"
|
11
12
|
gem "hanami-router"
|
12
|
-
|
13
|
-
gem "
|
13
|
+
gem "rack-multiplexer"
|
14
|
+
gem "sinatra"
|
data/bench/Rakefile.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
desc "run 'bench.rb' script"
|
6
6
|
task :bench, :N do |t, args|
|
7
7
|
n = args[:N] || 1000000
|
8
|
-
ruby "bench.rb", "
|
9
|
-
#ruby "bench.rb", "
|
10
|
-
#ruby "bench.rb", "
|
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
11
|
end
|