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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ffb2322f3ac227a3d07fa95c120d25c3dcb8763f9ea925be7a3a03df11c00ba9
4
- data.tar.gz: 60b292dd4a1307a2fd1cbfcb474746131599fe0ba0ae93768b40f2cf0c9e5fa5
3
+ metadata.gz: 9f8d5e69ec9a40e0698eb97d91f28882b9398f19ec85d2a412a5e79c86efc8fe
4
+ data.tar.gz: 6d7f33be397ffe163fbe4ac87e050213c7f05fdef37adfc3a1189ccb2861d608
5
5
  SHA512:
6
- metadata.gz: d33fb4622786b549f6681f6a89fd578f631235548b7d67644431483815a71e62d0a438c22b82e2534074c52e704cd68607f02060153ea8477898e13725c3e836
7
- data.tar.gz: 36be6953b2ed04a82f56c97e0c3eaf51022b21546116a0ead5b1a125ff82c746c1297a9c4e153012ca0a922e1a55161a1ea7a534036857d97cd91529aa4118d9
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.0 $)
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