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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 55c3dc8f5747e61e864ee478f7336d755dc022cb4ebc2f75baeae2b2f1059bd8
4
- data.tar.gz: '085324025413ff2d565f6aad7d8fc1827486d9454772f3c745fb1bd3f3d575f3'
3
+ metadata.gz: 9f8d5e69ec9a40e0698eb97d91f28882b9398f19ec85d2a412a5e79c86efc8fe
4
+ data.tar.gz: 6d7f33be397ffe163fbe4ac87e050213c7f05fdef37adfc3a1189ccb2861d608
5
5
  SHA512:
6
- metadata.gz: 357cfa2babfeb364ff8ca485247eed0f1cb9f7a0c5d7c5ff7c907d593d488bb3e365e198cb6eaf89328b7f85c3e349e273793ade17ee1e94822eed139df90bd0
7
- data.tar.gz: a6bb2a5d973fa092f356b733ce4ca5f1af335ec53f7d83f9087e0dec271ada489ae80576ba71a4199dd084a6ffc3a25e74e6c29d8e2a1ff0c0e535e2fcf83e8e
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.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
- ['/' , welcome_app],
104
- ['/api', [
105
- ['/books', [
106
- ['' , books_api],
107
- ['/:id(.:format)' , book_api],
108
- ['/:book_id/comments/:comment_id', comment_api],
109
- ]],
110
- ]],
111
- ['/admin', [
112
- ['/books' , admin_books_app],
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
- ['/' , {GET: welcome_app}],
135
- ['/api', [
136
- ['/books', [
137
- ['' , {GET: book_list_api, POST: book_create_api}],
138
- ['/:id(.:format)' , {GET: book_show_api, PUT: book_update_api}],
139
- ['/:book_id/comments/:comment_id', {POST: comment_create_api}],
140
- ]],
141
- ]],
142
- ['/admin', [
143
- ['/books' , {ANY: admin_books_app}],
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
- ['/api', [
184
- ['/books', [
185
- ['' , {GET: [BooksAPI, :index],
186
- POST: [BooksAPI, :create]}],
187
- ['/:id' , {GET: [BooksAPI, :show],
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('/api/books/123')
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, action = dict["GET"]
193
+ klass, method_name = dict["GET"]
198
194
  handler = klass.new(Rack::Request.new(env), Rack::Response.new)
199
- handler.__send__(action, args)
195
+ handler.__send__(method_name, args)
200
196
  ```
201
197
 
202
198
 
203
199
  ## Topics
204
200
 
205
201
 
206
- ### Nested Array v.s. Nested Hash
202
+ ### Nested Hash v.s. Nested Array
207
203
 
208
- URL path mapping can be not only nested Array but also nested Hash.
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
- 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.
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
- ## NOT OK
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
- def Map(**kwargs) # helper method to create subclass object
254
- return Map.new.update(kwargs)
255
- end
256
-
257
- ## OK
243
+ ## Not OK
258
244
  mapping = {
259
245
  "/api" => {
260
246
  "/books" => {
261
- "" => Map(GET: book_list_api, POST: book_create_api),
262
- "/:id" => Map(GET: book_show_api, PUT: book_update_api),
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
- ["/api/books/:book_id", rack_app]
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 "sinatra"
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 "benchmarker"
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", "--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"
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