rack-jet_router 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +16 -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 +121 -62
- data/rack-jet_router.gemspec +1 -1
- data/test/builder_test.rb +136 -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,22 @@ 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
|
+
|
15
|
+
Release 1.3.1 (2023-12-10)
|
16
|
+
--------------------------
|
17
|
+
|
18
|
+
* [bugfix] Fixed to correctly handle suffixed URL path pattern such as `/foo(.:format)`.
|
19
|
+
|
20
|
+
|
5
21
|
Release 1.3.0 (2023-12-09)
|
6
22
|
--------------------------
|
7
23
|
|
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
|