hanami-router 2.0.0.alpha5 → 2.0.0.beta2

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: d72d9efd8d4b3b0df52796170481b05878e531b2aee3ea09894e6eeccb5562e6
4
- data.tar.gz: 2078b5956054db900fe4d2f097b62901499ceb1622a57baae326fa921ef62f48
3
+ metadata.gz: 81061c98f91ba599e04ca8e16ac1ae9f8784e8398f3580b552cfa26885218b2e
4
+ data.tar.gz: cd776fa30375c022808441897e3849ec76ef5a6d5b452b36a444851c10a4f99c
5
5
  SHA512:
6
- metadata.gz: 5409a722ae69fc035fcbe54138ecfe504d97d9dcd62f0c3ce04a93f2fa5ca40aa833813b491a3a13d1db972e8e352e9d7e89948dfa3f522d99beafae4908e961
7
- data.tar.gz: 55505b92589cb74795bd01a6062d32effce16a56d0405b98e726d0ba9d3b54ca301fb464cf0826fdac7e45f1de23a15913a211359c2f908117b1e972684b90d7
6
+ metadata.gz: 3cdc82d97486a5d74893d8fdff7bd1f337dc5d64d6ff6407133519aef0b8a287b369231d973b62a4da5fdee7d07ecb766d3d0fd39a8e08aa3cd966a425fff238
7
+ data.tar.gz: ccc62d079fba4374b74dde5b008e3de0d4d5eaf630c9608179bca0ad0ff7ba6b0584713bb320977950f7901d0404b601598b2d6c97ffa218be428e8be47b2380
data/CHANGELOG.md CHANGED
@@ -1,39 +1,81 @@
1
1
  # Hanami::Router
2
+
2
3
  Rack compatible HTTP router for Ruby
3
4
 
5
+ ## v2.0.0.beta2 - 2022-08-16
6
+
7
+ ### Fixed
8
+
9
+ - [Luca Guidi] [Internal] Ensure `Hanami::Middleware::Error` class is available where it is needed [#225]
10
+
11
+ ## v2.0.0.beta1 - 2022-07-20
12
+
13
+ ### Added
14
+
15
+ - [Marc Busqué] Introduced `Hanami::Router::Formatter::CSV` for CSV inspection of the routes
16
+
17
+ ### Fixed
18
+
19
+ - [Marc Busqué] Routes inspection: Don't print empty line after the definition of a `get` route
20
+ - [Marc Busqué] Routes inspection: Print `<controller>.<action>` instead of `(proc)`
21
+ - [Marc Busqué] Routes inspection: Print `(block)` instead of `NilClass` when inspecting a route block
22
+
23
+ ## v2.0.0.alpha6 - 2022-02-10
24
+
25
+ ### Added
26
+
27
+ - [Luca Guidi] Official support for MRI 3.1
28
+ - [Luca Guidi] Parse non-GET request body and make it available in Rack env under the `router.params` key. For JSON requests, please use `Hanami:::Middleware::JsonParser`
29
+
30
+ ### Changed
31
+
32
+ - [Luca Guidi] Drop support for Ruby: MRI 2.6, and 2.7.
33
+
4
34
  ## v2.0.0.alpha5 - 2021-05-04
35
+
5
36
  ### Added
37
+
6
38
  - [Luca Guidi] Introduced `Hanami::Router#to_inspect` which returns a string blob with all the routes formatted for human readability
7
39
 
8
40
  ## v2.0.0.alpha4 - 2021-01-16
41
+
9
42
  ### Added
43
+
10
44
  - [Luca Guidi] Official support for MRI 3.0
11
45
  - [Luca Guidi] Introduced `Hanami::Middleware::BodyParser::Parser` as superclass for body parsers
12
46
  - [Paweł Świątkowski] Added `not_found:` option to `Hanami::Router#initialize` to customize HTTP 404 status
13
47
 
14
48
  ## v2.0.0.alpha3 - 2020-05-20
49
+
15
50
  ### Fixed
51
+
16
52
  - [Luca Guidi] `Hanami::Router#initialize` do not yield block if not given
17
53
  - [Luca Guidi] Ensure to not accidentally cache response headers for HTTP 404 and 405
18
54
  - [Luca Guidi] Ensure scoped root to not be added as trailing slash
19
55
 
20
56
  ## v2.0.0.alpha2 - 2020-02-19
57
+
21
58
  ### Added
59
+
22
60
  - [Luca Guidi] Block syntax. Routes definition accept a block which returning value is the body of the Rack response.
23
61
  - [Luca Guidi] Added `resolver:` option to `Hanami::Router#initialize` to provide your own strategy to load endpoints.
24
62
 
25
63
  ### Changed
64
+
26
65
  - [Luca Guidi] Removed `Hanami::Router#resource` and `#resources`.
27
66
  - [Luca Guidi] Removed loading of routes endpoints.
28
67
  - [Luca Guidi] Removed `inflector:` from `Hanami::Router#initialize`
29
68
  - [Luca Guidi] Removed `scheme:`, `host:`, `port:` from `Hanami::Router#initialize`, use `base_url:` instead.
30
69
 
31
70
  ## v2.0.0.alpha1 - 2019-01-30
71
+
32
72
  ### Added
73
+
33
74
  - [Luca Guidi] Introduce `Hanami::Router#scope` to support single routing tier for Hanami
34
75
  - [Semyon Pupkov] Added `inflector:` option for `Hanami::Router#initialize` based on `dry-inflector`
35
76
 
36
77
  ### Changed
78
+
37
79
  - [Luca Guidi] Drop support for Ruby: MRI 2.3, and 2.4.
38
80
  - [Luca Guidi] Renamed `Hanami::Router#namespace` => `#prefix`
39
81
  - [Gustavo Caso] Remove body cleanup for `HEAD` requests
@@ -45,25 +87,34 @@ Rack compatible HTTP router for Ruby
45
87
  - [Luca Guidi] `Hanami::Router#initialize` requires `configuration:` option if routes endpoints are `Hanami::Action` subclasses
46
88
 
47
89
  ## v1.3.2 - 2019-02-13
90
+
48
91
  ### Added
92
+
49
93
  - [Luca Guidi] Official support for Ruby: MRI 2.7
50
94
  - [Luca Guidi] Support `rack` 2.1
51
95
 
52
96
  ## v1.3.1 - 2019-01-18
97
+
53
98
  ### Added
99
+
54
100
  - [Luca Guidi] Official support for Ruby: MRI 2.6
55
101
  - [Luca Guidi] Support `bundler` 2.0+
56
102
 
57
103
  ## v1.3.0 - 2018-10-24
104
+
58
105
  ### Fixed
106
+
59
107
  - [Tim Riley] Skip attempting to parse unknown types in `Hanami::Middleware::BodyParser`
60
108
 
61
109
  ## v1.3.0.beta1 - 2018-08-08
110
+
62
111
  ### Added
112
+
63
113
  - [Luca Guidi] Official support for JRuby 9.2.0.0
64
114
  - [Gustavo Caso] Introduce `Hanami::Middleware::BodyParser` Rack middleware to parse payload of non-GET HTTP requests.
65
115
 
66
116
  ### Deprecated
117
+
67
118
  - [Alfonso Uceda] Deprecate `Hanami::Router.new(force_ssl: true)`. Use webserver (eg. Nginx), Rack middleware (eg. `rack-ssl`), or another strategy to force HTTPS connection.
68
119
  - [Gustavo Caso] Deprecate `Hanami::Router.new(body_parsers: [:json])`. Use `Hanami::Middleware::BodyParser` instead.
69
120
 
@@ -78,16 +129,21 @@ Rack compatible HTTP router for Ruby
78
129
  ## v1.2.0.beta1 - 2018-02-28
79
130
 
80
131
  ## v1.1.1 - 2018-02-27
132
+
81
133
  ### Added
134
+
82
135
  - [Luca Guidi] Official support for Ruby: MRI 2.5
83
136
 
84
137
  ### Fixed
138
+
85
139
  - [malin-as] Ensure `Hanami::Router` to properly respond to `unlink`
86
140
 
87
141
  ## v1.1.0 - 2017-10-25
88
142
 
89
143
  ## v1.1.0.rc1 - 2017-10-16
144
+
90
145
  ### Added
146
+
91
147
  - [Sergey Fedorov] Allow Rack applications to be mounted inside a namespace. (`namespace "api" { mount V1::App, at: "/v1" }`)
92
148
 
93
149
  ## v1.1.0.beta3 - 2017-10-04
@@ -97,10 +153,13 @@ Rack compatible HTTP router for Ruby
97
153
  ## v1.1.0.beta1 - 2017-08-11
98
154
 
99
155
  ## v1.0.1 - 2017-07-10
156
+
100
157
  ### Added
158
+
101
159
  - [Luca Guidi] Introduce new introspection methods (`#redirect?` and `#redirection_path`) for recognized routes (see `Hanami::Router#recognize`)
102
160
 
103
161
  ### Fixed
162
+
104
163
  - [Luca Guidi] Ensure `Hanami::Router#redirect` to be compatible with `#recognize`
105
164
 
106
165
  ## v1.0.0 - 2017-04-06
@@ -110,131 +169,176 @@ Rack compatible HTTP router for Ruby
110
169
  ## v1.0.0.beta3 - 2017-03-17
111
170
 
112
171
  ## v1.0.0.beta2 - 2017-03-02
172
+
113
173
  ### Fixed
174
+
114
175
  - [Valentyn Ostakh] Deep symbolize params from parsed body
115
176
  - [Luca Guidi] `Hanami::Router#recognize` must return a non-routeable object when the endpoint cannot be resolved
116
177
 
117
178
  ## v1.0.0.beta1 - 2017-02-14
179
+
118
180
  ### Added
181
+
119
182
  - [Luca Guidi] Official support for Ruby: MRI 2.4
120
183
  - [Jakub Pavlík] Added `:as` option for RESTful resources (eg. `resources :psi, controller: 'dogs', as: 'dogs'`)
121
184
 
122
185
  ### Changed
186
+
123
187
  - [Pascal Betz] Make compatible with Rack 2.0 only
124
188
 
125
189
  ## v0.8.1 - 2016-11-18
190
+
126
191
  ### Fixed
192
+
127
193
  - [Luca Guidi] Ensure JSON body parser to not eval untrusted input
128
194
 
129
195
  ## v0.8.0 - 2016-11-15
196
+
130
197
  ### Added
198
+
131
199
  - [Kyle Chong] Referenced params from body parses in Rack env via `router.parsed_body`
132
200
 
133
201
  ### Fixed
202
+
134
203
  - [Luca Guidi & Lucas Hosseini] Ensure params from routes take precedence over params from body parsing
135
204
  - [Luca Guidi] Ensure inspector to respect path prefix of mouted apps
136
205
 
137
206
  ### Changed
207
+
138
208
  - [Luca Guidi] Official support for Ruby: MRI 2.3+ and JRuby 9.1.5.0+
139
209
 
140
210
  ## v0.7.0 - 2016-07-22
211
+
141
212
  ### Added
213
+
142
214
  - [Sean Collins] Introduced `Hanami::Router#root`. Example: `root to: 'home#index'`, equivalent to `get '/', to: 'home#index', as: :root`.
143
215
  - [Nicola Racco] Allow to mount Rack applications at a specific host. Example: `mount Blog, host: 'blog'`, which will be hit for `GET http://blog.example.com`
144
216
  - [Luca Guidi] Support `multi_json` gem as backend for JSON body parser. If `multi_json` is present in the gem bundle, it will be used, otherwise it will fallback to Ruby's `JSON`.
145
217
  - [Luca Guidi] Introduced `Hanami::Routing::RecognizedRoute#path` in order to allow a better introspection
146
218
 
147
219
  ### Fixed
220
+
148
221
  - [Andrew De Ponte] Make routes inspection to work when non-Hanami apps are mounted
149
222
  - [Andrew De Ponte] Ensure to set the right `SCRIPT_NAME` in Rack env for mounted Hanami apps
150
223
  - [Luca Guidi] Fix `NoMethodError` when `Hanami::Router#recognize` is invoked with a Rack env or a route name or a path that can't be recognized
151
224
 
152
225
  ### Changed
226
+
153
227
  – [Luca Guidi] Drop support for Ruby 2.0 and 2.1. Official support for JRuby 9.0.5.0+
154
228
 
155
229
  ## v0.6.2 - 2016-02-05
230
+
156
231
  ### Fixed
232
+
157
233
  - [Anton Davydov] Fix double leading slash for Capybara's `current_path`
158
234
 
159
235
  ## v0.6.1 - 2016-01-27
236
+
160
237
  ### Fixed
238
+
161
239
  - [Luca Guidi] Fix body parsers for non Hash requests
162
240
 
163
241
  ## v0.6.0 - 2016-01-22
242
+
164
243
  ### Changed
244
+
165
245
  - [Luca Guidi] Renamed the project
166
246
 
167
247
  ## v0.5.1 - 2016-01-19
248
+
168
249
  - [Anton Davydov] Print stacked lines for routes inspection
169
250
 
170
251
  ## v0.5.0 - 2016-01-12
252
+
171
253
  ### Added
254
+
172
255
  - [Luca Guidi] Added `Lotus::Router#recognize` as a testing facility. Example `router.recognize('/') # => associated route`
173
256
  - [Luca Guidi] Added `Lotus::Router.define` in order to wrap routes definitions in `config/routes.rb` when `Lotus::Router` is used outside of Lotus projects
174
257
  - [David Strauß] Make `Lotus::Routing::Parsing::JsonParser` compatible with `application/vnd.api+json` MIME Type
175
258
  - [Alfonso Uceda Pompa] Improved exception messages for `Lotus::Router#path` and `#url`
176
259
 
177
260
  ### Fixed
261
+
178
262
  - [Alfonso Uceda Pompa] Ensure `Lotus::Router#path` and `#url` to generate correct URL for mounted applications
179
263
  - [Vladislav Zarakovsky] Ensure Force SSL mode to respect Rack SPEC
180
264
 
181
265
  ### Changed
266
+
182
267
  - [Alfonso Uceda Pompa] A failure for body parsers raises a `Lotus::Routing::Parsing::BodyParsingError` exception
183
268
  - [Karim Tarek] Introduced `Lotus::Router::Error` and let all the framework exceptions to inherit from it.
184
269
 
185
270
  ## v0.4.3 - 2015-09-30
271
+
186
272
  ### Added
273
+
187
274
  - [Luca Guidi] Official support for JRuby 9k+
188
275
 
189
276
  ## v0.4.2 - 2015-07-10
277
+
190
278
  ### Fixed
279
+
191
280
  - [Alfonso Uceda Pompa] Ensure mounted applications to not repeat their prefix (eg `/admin/admin`)
192
281
  - [Thiago Felippe] Ensure router inspector properly prints routes with repeated entries (eg `/admin/dashboard/admin`)
193
282
 
194
283
  ## v0.4.1 - 2015-06-23
284
+
195
285
  ### Added
286
+
196
287
  - [Alfonso Uceda Pompa] Force SSL (eg `Lotus::Router.new(force_ssl: true`).
197
288
  - [Alfonso Uceda Pompa] Allow router to accept a `:prefix` option, in order to generate prefixed routes.
198
289
 
199
290
  ## v0.4.0 - 2015-05-15
291
+
200
292
  ### Added
293
+
201
294
  - [Alfonso Uceda Pompa] Nested RESTful resource(s)
202
295
 
203
296
  ### Changed
297
+
204
298
  - [Alfonso Uceda Pompa] RESTful resource(s) have a correct pluralization/singularization for variables and named routes (eg. `/books/:id` is now `:book` instead of `:books`)
205
299
 
206
300
  ## v0.3.0 - 2015-03-23
207
301
 
208
302
  ## v0.2.1 - 2015-01-30
303
+
209
304
  ### Added
305
+
210
306
  - [Alfonso Uceda Pompa] Lotus::Action compat: invoke `.call` if defined, otherwise fall back to `#call`.
211
307
 
212
308
  ## v0.2.0 - 2014-12-23
309
+
213
310
  ### Added
311
+
214
312
  - [Luca Guidi & Alfonso Uceda Pompa] Introduced routes inspector for CLI
215
313
  - [Luca Guidi & Janko Marohnić] Introduced body parser for JSON
216
314
  - [Luca Guidi] Introduced request body parsers: they parse body and turn into params.
217
315
  - [Fred Wu] Introduced Router#define
218
316
 
219
317
  ### Fixed
318
+
220
319
  - [Luca Guidi] Fix for member/collection actions in RESTful resource(s): allow to take actions with a leading slash.
221
320
  - [Janko Marohnić] Fix for nested namespaces and RESTful resource(s) under namespace. They were generating wrong route names.
222
321
  - [Luca Guidi] Made InvalidRouteException to inherit from StandardError so it can be catched from anonymous `rescue` clause
223
322
  - [Luca Guidi] Fix RESTful resource(s) to respect :only/:except options
224
323
 
225
324
  ### Changed
325
+
226
326
  - [Luca Guidi] Aligned naming conventions with Lotus::Controller: no more BooksController::Index. Use Books::Index instead.
227
327
  - [Luca Guidi] Removed `:prefix` option for routes. Use `#namespace` blocks instead.
228
328
  - [Janko Marohnić] Make 301 the default redirect status
229
329
 
230
330
  ## v0.1.1 - 2014-06-23
331
+
231
332
  ### Added
333
+
232
334
  - [Luca Guidi] Introduced Lotus::Router#mount
233
335
  - [Luca Guidi] Let specify a pattern for Lotus::Routing::EndpointResolver
234
336
  - [Luca Guidi] Make Lotus::Routing::Endpoint::EndpointNotFound to inherit from StandardError, instead of Exception. This make it compatible with Rack::ShowExceptions.
235
337
 
236
338
  ## v0.1.0 - 2014-01-23
339
+
237
340
  ### Added
341
+
238
342
  - [Luca Guidi] Official support for Ruby 2.1
239
343
  - [Luca Guidi] Added support for OPTIONS HTTP verb
240
344
  - [Luca Guidi] Added Lotus::Routing::EndpointNotFound when a lazy endpoint can't be found
data/README.md CHANGED
@@ -2,11 +2,15 @@
2
2
 
3
3
  Rack compatible, lightweight and fast HTTP Router for Ruby and [Hanami](http://hanamirb.org).
4
4
 
5
+ ## Version
6
+
7
+ **This branch contains the code for `hanami-router` 2.x.**
8
+
5
9
  ## Status
6
10
 
7
11
  [![Gem Version](https://badge.fury.io/rb/hanami-router.svg)](https://badge.fury.io/rb/hanami-router)
8
- [![CI](https://github.com/hanami/router/workflows/ci/badge.svg?branch=unstable)](https://github.com/hanami/router/actions?query=workflow%3Aci+branch%3Aunstable)
9
- [![Test Coverage](https://codecov.io/gh/hanami/router/branch/unstable/graph/badge.svg)](https://codecov.io/gh/hanami/router)
12
+ [![CI](https://github.com/hanami/router/workflows/ci/badge.svg?branch=main)](https://github.com/hanami/router/actions?query=workflow%3Aci+branch%3Amain)
13
+ [![Test Coverage](https://codecov.io/gh/hanami/router/branch/main/graph/badge.svg)](https://codecov.io/gh/hanami/router)
10
14
  [![Depfu](https://badges.depfu.com/badges/5f6b8e8fa3b0d082539f0b0f84d55960/overview.svg)](https://depfu.com/github/hanami/router?project=Bundler)
11
15
  [![Inline Docs](http://inch-ci.org/github/hanami/router.svg)](http://inch-ci.org/github/hanami/router)
12
16
 
@@ -21,7 +25,7 @@ Rack compatible, lightweight and fast HTTP Router for Ruby and [Hanami](http://h
21
25
 
22
26
  ## Rubies
23
27
 
24
- __Hanami::Router__ supports Ruby (MRI) 2.6+
28
+ __Hanami::Router__ supports Ruby (MRI) 3.0+
25
29
 
26
30
 
27
31
  ## Installation
@@ -361,6 +365,4 @@ __Hanami::Router__ uses [Semantic Versioning 2.0.0](http://semver.org)
361
365
 
362
366
  ## Copyright
363
367
 
364
- Copyright © 2014-2021 Luca Guidi – Released under MIT License
365
-
366
- This project was formerly known as Lotus (`lotus-router`).
368
+ Copyright © 2014-2022 Hanami Team – Released under MIT License
@@ -16,9 +16,9 @@ Gem::Specification.new do |spec|
16
16
 
17
17
  spec.files = `git ls-files -- lib/* CHANGELOG.md LICENSE.md README.md hanami-router.gemspec`.split($/)
18
18
  spec.executables = []
19
- spec.test_files = spec.files.grep(%r{^(test)/})
20
19
  spec.require_paths = ["lib"]
21
- spec.required_ruby_version = ">= 2.6.0"
20
+ spec.metadata["rubygems_mfa_required"] = "true"
21
+ spec.required_ruby_version = ">= 3.0"
22
22
 
23
23
  spec.add_dependency "rack", "~> 2.0"
24
24
  spec.add_dependency "mustermann", "~> 1.0"
@@ -29,6 +29,6 @@ Gem::Specification.new do |spec|
29
29
  spec.add_development_dependency "rack-test", "~> 1.0"
30
30
  spec.add_development_dependency "rspec", "~> 3.8"
31
31
 
32
- spec.add_development_dependency "rubocop", "0.91"
33
- spec.add_development_dependency "rubocop-performance", "1.8.1"
32
+ spec.add_development_dependency "rubocop", "~> 1.0"
33
+ spec.add_development_dependency "rubocop-performance", "~> 1.0"
34
34
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "hanami/middleware/error"
4
+
3
5
  module Hanami
4
6
  module Middleware
5
7
  # @since 1.3.0
@@ -17,7 +17,7 @@ module Hanami
17
17
 
18
18
  # @since 1.3.0
19
19
  # @api private
20
- MEDIA_TYPE_MATCHER = /\s*[;,]\s*/.freeze
20
+ MEDIA_TYPE_MATCHER = /\s*[;,]\s*/
21
21
 
22
22
  # @since 1.3.0
23
23
  # @api private
@@ -5,7 +5,7 @@ module Hanami
5
5
  #
6
6
  # @since 1.3.0
7
7
  module Middleware
8
- unless defined?(Error)
8
+ unless defined?(::Hanami::Middleware::Error)
9
9
  # Base error for Rack middleware
10
10
  #
11
11
  # @since 2.0.0
@@ -35,7 +35,7 @@ module Hanami
35
35
  if value
36
36
  @status = value
37
37
  else
38
- @status ||= 200
38
+ @status ||= Router::HTTP_STATUS_OK
39
39
  end
40
40
  end
41
41
 
@@ -59,7 +59,7 @@ module Hanami
59
59
  #
60
60
  # @since 2.0.0
61
61
  def params
62
- env["router.params"]
62
+ env[Router::PARAMS]
63
63
  end
64
64
 
65
65
  # @api private
@@ -60,7 +60,7 @@ module Hanami
60
60
  class NotRoutableEndpointError < Error
61
61
  # @since 0.5.0
62
62
  def initialize(env)
63
- super %(Cannot find routable endpoint for: #{env['REQUEST_METHOD']} #{env['PATH_INFO']})
63
+ super %(Cannot find routable endpoint for: #{env[::Rack::REQUEST_METHOD]} #{env[::Rack::PATH_INFO]})
64
64
  end
65
65
  end
66
66
  end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "csv"
4
+
5
+ module Hanami
6
+ class Router
7
+ # Renders a CSV representation of the routes
8
+ #
9
+ # You can forward [CSV generation
10
+ # options](https://ruby-doc.org/stdlib-3.1.0/libdoc/csv/rdoc/CSV.html#class-CSV-label-Options+for+Generating]
11
+ # when calling it:
12
+ #
13
+ # ```
14
+ # require "hanami/router/inspector"
15
+ # require "hanami/router/formatter/csv"
16
+ #
17
+ # Hanami::Router::Inspector.new(
18
+ # routes: Router.routes,
19
+ # formatter: Hanami::Router::Formatter::CSV.new
20
+ # ).call(write_headers: false)
21
+ # ```
22
+ #
23
+ # @api private
24
+ # @since 2.0.0
25
+ module Formatter
26
+ class CSV
27
+ # @api private
28
+ # @since 2.0.0
29
+ DEFAULT_OPTIONS = {
30
+ write_headers: true
31
+ }.freeze
32
+
33
+ # @api private
34
+ # @since 2.0.0
35
+ HEADERS = %w[METHOD PATH TO AS CONSTRAINTS].freeze
36
+
37
+ # @api private
38
+ # @since 2.0.0
39
+ def call(routes, **csv_opts)
40
+ ::CSV.generate(**DEFAULT_OPTIONS.merge(csv_opts)) do |csv|
41
+ csv << HEADERS if csv.write_headers?
42
+ routes.reduce(csv) do |acc, route|
43
+ route.head? ? acc : acc << row(route)
44
+ end
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def row(route)
51
+ [
52
+ route.http_method.to_s,
53
+ route.path,
54
+ route.inspect_to,
55
+ route.as? ? route.inspect_as : "",
56
+ route.constraints? ? route.inspect_constraints : ""
57
+ ]
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hanami
4
+ class Router
5
+ # Renders a human friendly representation of the routes
6
+ #
7
+ # @api private
8
+ # @since 2.0.0
9
+ module Formatter
10
+ class HumanFriendly
11
+ # @api private
12
+ # @since 2.0.0
13
+ NEW_LINE = $/
14
+ private_constant :NEW_LINE
15
+
16
+ # @api private
17
+ # @since 2.0.0
18
+ SMALL_STRING_JUSTIFY_AMOUNT = 8
19
+ private_constant :SMALL_STRING_JUSTIFY_AMOUNT
20
+
21
+ # @api private
22
+ # @since 2.0.0
23
+ MEDIUM_STRING_JUSTIFY_AMOUNT = 20
24
+ private_constant :MEDIUM_STRING_JUSTIFY_AMOUNT
25
+
26
+ # @api private
27
+ # @since 2.0.0
28
+ LARGE_STRING_JUSTIFY_AMOUNT = 30
29
+ private_constant :LARGE_STRING_JUSTIFY_AMOUNT
30
+
31
+ # @api private
32
+ # @since 2.0.0
33
+ EXTRA_LARGE_STRING_JUSTIFY_AMOUNT = 40
34
+ private_constant :EXTRA_LARGE_STRING_JUSTIFY_AMOUNT
35
+
36
+ # @api private
37
+ # @since 2.0.0
38
+ def call(routes)
39
+ routes.filter_map(&method(:format_route_unless_head)).join(NEW_LINE)
40
+ end
41
+
42
+ private
43
+
44
+ def format_route_unless_head(route)
45
+ !route.head? &&
46
+ [
47
+ route.http_method.to_s.ljust(SMALL_STRING_JUSTIFY_AMOUNT),
48
+ route.path.ljust(LARGE_STRING_JUSTIFY_AMOUNT),
49
+ route.inspect_to.ljust(LARGE_STRING_JUSTIFY_AMOUNT),
50
+ route.as? ? "as #{route.inspect_as}".ljust(MEDIUM_STRING_JUSTIFY_AMOUNT) : "",
51
+ route.constraints? ? "(#{route.inspect_constraints})".ljust(EXTRA_LARGE_STRING_JUSTIFY_AMOUNT) : ""
52
+ ].join
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,16 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "hanami/router/formatter/human_friendly"
4
+
3
5
  module Hanami
4
6
  class Router
5
7
  # Routes inspector
6
8
  #
7
- # @api private
9
+ # Builds a representation of an array of routes according to a given
10
+ # formatter.
11
+ #
8
12
  # @since 2.0.0
9
13
  class Inspector
10
- # @api private
14
+ # @param routes [Array<Hanami::Route>]
15
+ # @param formatter [#call] Takes the routes as an argument and returns
16
+ # whatever representation it creates. Defaults to
17
+ # {Hanami::Router::Formatter::HumanFriendly}.
11
18
  # @since 2.0.0
12
- def initialize(routes: [])
19
+ def initialize(routes: [], formatter: Formatter::HumanFriendly.new)
13
20
  @routes = routes
21
+ @formatter = formatter
14
22
  end
15
23
 
16
24
  # @param route [Hash] serialized route
@@ -21,18 +29,12 @@ module Hanami
21
29
  @routes.push(route)
22
30
  end
23
31
 
24
- # @return [String] The inspected routes
32
+ # @return [Any] Formatted routes
25
33
  #
26
- # @api private
27
34
  # @since 2.0.0
28
- def call(*)
29
- @routes.map(&:to_inspect).join(NEW_LINE)
35
+ def call(...)
36
+ @formatter.call(@routes, ...)
30
37
  end
31
-
32
- # @api private
33
- # @since 2.0.0
34
- NEW_LINE = $/
35
- private_constant :NEW_LINE
36
38
  end
37
39
  end
38
40
  end
@@ -72,7 +72,7 @@ module Hanami
72
72
  # @api private
73
73
  # @since 2.0.0
74
74
  def variable?(segment)
75
- /:/.match?(segment)
75
+ Router::ROUTE_VARIABLE_MATCHER.match?(segment)
76
76
  end
77
77
 
78
78
  # @api private
@@ -48,11 +48,11 @@ module Hanami
48
48
 
49
49
  # @since 2.0.0
50
50
  # @api private
51
- DEFAULT_SEPARATOR_REGEXP = /\//.freeze
51
+ DEFAULT_SEPARATOR_REGEXP = /\//
52
52
 
53
53
  # @since 2.0.0
54
54
  # @api private
55
- DOUBLE_DEFAULT_SEPARATOR_REGEXP = /\/{2,}/.freeze
55
+ DOUBLE_DEFAULT_SEPARATOR_REGEXP = /\/{2,}/
56
56
 
57
57
  # @since 2.0.0
58
58
  # @api private
@@ -41,7 +41,7 @@ module Hanami
41
41
  # @since 0.5.0
42
42
  # @api public
43
43
  def verb
44
- @env["REQUEST_METHOD"]
44
+ @env[::Rack::REQUEST_METHOD]
45
45
  end
46
46
 
47
47
  # Relative URL (path)
@@ -51,13 +51,13 @@ module Hanami
51
51
  # @since 0.7.0
52
52
  # @api public
53
53
  def path
54
- @env["PATH_INFO"]
54
+ @env[::Rack::PATH_INFO]
55
55
  end
56
56
 
57
57
  # @since 0.7.0
58
58
  # @api public
59
59
  def params
60
- @env["router.params"]
60
+ @env[Router::PARAMS]
61
61
  end
62
62
 
63
63
  # @since 0.7.0
@@ -5,24 +5,27 @@ require "hanami/router/block"
5
5
 
6
6
  module Hanami
7
7
  class Router
8
+ # A route from the router
9
+ #
10
+ # @since 2.0.0
8
11
  class Route
9
12
  # @api private
13
+ # @since 2.0.0
14
+ ROUTE_CONSTRAINT_SEPARATOR = ", "
15
+ private_constant :ROUTE_CONSTRAINT_SEPARATOR
16
+
10
17
  # @since 2.0.0
11
18
  attr_reader :http_method
12
19
 
13
- # @api private
14
20
  # @since 2.0.0
15
21
  attr_reader :path
16
22
 
17
- # @api private
18
23
  # @since 2.0.0
19
24
  attr_reader :to
20
25
 
21
- # @api private
22
26
  # @since 2.0.0
23
27
  attr_reader :as
24
28
 
25
- # @api private
26
29
  # @since 2.0.0
27
30
  attr_reader :constraints
28
31
 
@@ -38,93 +41,50 @@ module Hanami
38
41
  freeze
39
42
  end
40
43
 
41
- # @api private
42
44
  # @since 2.0.0
43
- def to_inspect
44
- return EMPTY_ROUTE if head?
45
-
46
- result = http_method.to_s.ljust(SMALL_STRING_JUSTIFY_AMOUNT)
47
- result += path.ljust(LARGE_STRING_JUSTIFY_AMOUNT)
48
- result += inspect_to(to).ljust(LARGE_STRING_JUSTIFY_AMOUNT)
49
- result += "as #{as.inspect}".ljust(MEDIUM_STRING_JUSTIFY_AMOUNT) if as
50
-
51
- if constraints?
52
- result += "(#{inspect_constraints(constraints)})".ljust(EXTRA_LARGE_STRING_JUSTIFY_AMOUNT)
53
- end
54
-
55
- result
45
+ def head?
46
+ http_method == ::Rack::HEAD
56
47
  end
57
48
 
58
- private
59
-
60
- # @api private
61
49
  # @since 2.0.0
62
- EMPTY_ROUTE = ""
63
- private_constant :EMPTY_ROUTE
64
-
65
- # @api private
66
- # @since 2.0.0
67
- ROUTE_CONSTRAINT_SEPARATOR = ", "
68
- private_constant :ROUTE_CONSTRAINT_SEPARATOR
69
-
70
- # @api private
71
- # @since 2.0.0
72
- SMALL_STRING_JUSTIFY_AMOUNT = 8
73
- private_constant :SMALL_STRING_JUSTIFY_AMOUNT
74
-
75
- # @api private
76
- # @since 2.0.0
77
- MEDIUM_STRING_JUSTIFY_AMOUNT = 20
78
- private_constant :MEDIUM_STRING_JUSTIFY_AMOUNT
79
-
80
- # @api private
81
- # @since 2.0.0
82
- LARGE_STRING_JUSTIFY_AMOUNT = 30
83
- private_constant :LARGE_STRING_JUSTIFY_AMOUNT
84
-
85
- # @api private
86
- # @since 2.0.0
87
- EXTRA_LARGE_STRING_JUSTIFY_AMOUNT = 40
88
- private_constant :EXTRA_LARGE_STRING_JUSTIFY_AMOUNT
89
-
90
- # @api private
91
- # @since 2.0.0
92
- def head?
93
- http_method == "HEAD"
50
+ def as?
51
+ !as.nil?
94
52
  end
95
53
 
96
- # @api private
97
54
  # @since 2.0.0
98
55
  def constraints?
99
56
  constraints.any?
100
57
  end
101
58
 
102
- # @api private
103
59
  # @since 2.0.0
104
- def inspect_to(to)
105
- case to
60
+ def inspect_to(value = to)
61
+ case value
106
62
  when String
107
- to
63
+ value
108
64
  when Proc
109
65
  "(proc)"
110
66
  when Class
111
- to.name || "(class)"
67
+ value.name || "(class)"
112
68
  when Block
113
69
  "(block)"
114
70
  when Redirect
115
- "#{to.destination} (HTTP #{to.code})"
71
+ "#{value.destination} (HTTP #{to.code})"
116
72
  else
117
- inspect_to(to.class)
73
+ inspect_to(value.class)
118
74
  end
119
75
  end
120
76
 
121
- # @api private
122
77
  # @since 2.0.0
123
- def inspect_constraints(constraints)
124
- constraints.map do |key, value|
78
+ def inspect_constraints
79
+ @constraints.map do |key, value|
125
80
  "#{key}: #{value.inspect}"
126
81
  end.join(ROUTE_CONSTRAINT_SEPARATOR)
127
82
  end
83
+
84
+ # @since 2.0.0
85
+ def inspect_as
86
+ as ? as.inspect : Router::EMPTY_STRING
87
+ end
128
88
  end
129
89
  end
130
90
  end
@@ -52,10 +52,15 @@ module Hanami
52
52
 
53
53
  private
54
54
 
55
+ # @api private
56
+ # @since 2.0.0
57
+ SEGMENT_SEPARATOR = /\//
58
+ private_constant :SEGMENT_SEPARATOR
59
+
55
60
  # @api private
56
61
  # @since 2.0.0
57
62
  def for_each_segment(path, &blk)
58
- _, *segments = path.split(/\//)
63
+ _, *segments = path.split(SEGMENT_SEPARATOR)
59
64
  segments.each(&blk)
60
65
  end
61
66
  end
@@ -4,6 +4,6 @@ module Hanami
4
4
  class Router
5
5
  # @since 0.1.0
6
6
  # @api public
7
- VERSION = "2.0.0.alpha5"
7
+ VERSION = "2.0.0.beta2"
8
8
  end
9
9
  end
data/lib/hanami/router.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "rack"
3
4
  require "rack/utils"
4
5
 
5
6
  module Hanami
@@ -24,11 +25,12 @@ module Hanami
24
25
  # @since 2.0.0
25
26
  attr_reader :url_helpers
26
27
 
27
- # Routes for inspection
28
+ # Routes inspector
29
+ #
30
+ # @return [Hanami::Router::Inspector]
28
31
  #
29
- # @api private
30
32
  # @since 2.0.0
31
- attr_reader :routes
33
+ attr_reader :inspector
32
34
 
33
35
  # Returns the given block as it is.
34
36
  #
@@ -53,7 +55,7 @@ module Hanami
53
55
  # deployed
54
56
  # @param prefix [String] the relative URL prefix where the HTTP application
55
57
  # is deployed
56
- # @param resolver [#call(path, to)] a resolver for route entpoints
58
+ # @param resolver [#call(path, to)] a resolver for route endpoints
57
59
  # @param block_context [Hanami::Router::Block::Context)
58
60
  # @param not_found [#call(env)] default handler when route is not matched
59
61
  # @param blk [Proc] the route definitions
@@ -145,7 +147,7 @@ module Hanami
145
147
  # router.path(:root) # => "/"
146
148
  # router.url(:root) # => "https://hanamirb.org"
147
149
  def root(to: nil, &blk)
148
- get("/", to: to, as: :root, &blk)
150
+ get(ROOT_PATH, to: to, as: :root, &blk)
149
151
  end
150
152
 
151
153
  # Defines a route that accepts GET requests for the given path.
@@ -196,8 +198,8 @@ module Hanami
196
198
  # get "/users/:id", to: ->(*) { [200, {}, ["OK"]] }, id: /\d+/
197
199
  # end
198
200
  def get(path, to: nil, as: nil, **constraints, &blk)
199
- add_route("GET", path, to, as, constraints, &blk)
200
- add_route("HEAD", path, to, as, constraints, &blk)
201
+ add_route(::Rack::GET, path, to, as, constraints, &blk)
202
+ add_route(::Rack::HEAD, path, to, as, constraints, &blk)
201
203
  end
202
204
 
203
205
  # Defines a route that accepts POST requests for the given path.
@@ -215,7 +217,7 @@ module Hanami
215
217
  # @see #path
216
218
  # @see #url
217
219
  def post(path, to: nil, as: nil, **constraints, &blk)
218
- add_route("POST", path, to, as, constraints, &blk)
220
+ add_route(::Rack::POST, path, to, as, constraints, &blk)
219
221
  end
220
222
 
221
223
  # Defines a route that accepts PATCH requests for the given path.
@@ -233,7 +235,7 @@ module Hanami
233
235
  # @see #path
234
236
  # @see #url
235
237
  def patch(path, to: nil, as: nil, **constraints, &blk)
236
- add_route("PATCH", path, to, as, constraints, &blk)
238
+ add_route(::Rack::PATCH, path, to, as, constraints, &blk)
237
239
  end
238
240
 
239
241
  # Defines a route that accepts PUT requests for the given path.
@@ -251,7 +253,7 @@ module Hanami
251
253
  # @see #path
252
254
  # @see #url
253
255
  def put(path, to: nil, as: nil, **constraints, &blk)
254
- add_route("PUT", path, to, as, constraints, &blk)
256
+ add_route(::Rack::PUT, path, to, as, constraints, &blk)
255
257
  end
256
258
 
257
259
  # Defines a route that accepts DELETE requests for the given path.
@@ -269,7 +271,7 @@ module Hanami
269
271
  # @see #path
270
272
  # @see #url
271
273
  def delete(path, to: nil, as: nil, **constraints, &blk)
272
- add_route("DELETE", path, to, as, constraints, &blk)
274
+ add_route(::Rack::DELETE, path, to, as, constraints, &blk)
273
275
  end
274
276
 
275
277
  # Defines a route that accepts TRACE requests for the given path.
@@ -287,7 +289,7 @@ module Hanami
287
289
  # @see #path
288
290
  # @see #url
289
291
  def trace(path, to: nil, as: nil, **constraints, &blk)
290
- add_route("TRACE", path, to, as, constraints, &blk)
292
+ add_route(::Rack::TRACE, path, to, as, constraints, &blk)
291
293
  end
292
294
 
293
295
  # Defines a route that accepts OPTIONS requests for the given path.
@@ -305,7 +307,7 @@ module Hanami
305
307
  # @see #path
306
308
  # @see #url
307
309
  def options(path, to: nil, as: nil, **constraints, &blk)
308
- add_route("OPTIONS", path, to, as, constraints, &blk)
310
+ add_route(::Rack::OPTIONS, path, to, as, constraints, &blk)
309
311
  end
310
312
 
311
313
  # Defines a route that accepts LINK requests for the given path.
@@ -323,7 +325,7 @@ module Hanami
323
325
  # @see #path
324
326
  # @see #url
325
327
  def link(path, to: nil, as: nil, **constraints, &blk)
326
- add_route("LINK", path, to, as, constraints, &blk)
328
+ add_route(::Rack::LINK, path, to, as, constraints, &blk)
327
329
  end
328
330
 
329
331
  # Defines a route that accepts UNLINK requests for the given path.
@@ -341,7 +343,7 @@ module Hanami
341
343
  # @see #path
342
344
  # @see #url
343
345
  def unlink(path, to: nil, as: nil, **constraints, &blk)
344
- add_route("UNLINK", path, to, as, constraints, &blk)
346
+ add_route(::Rack::UNLINK, path, to, as, constraints, &blk)
345
347
  end
346
348
 
347
349
  # Defines a route that redirects the incoming request to another path.
@@ -451,7 +453,7 @@ module Hanami
451
453
  # router.path(:login, return_to: "/dashboard") # => "/login?return_to=%2Fdashboard"
452
454
  # router.path(:framework, name: "router") # => "/router"
453
455
  def path(name, variables = {})
454
- @url_helpers.path(name, variables)
456
+ url_helpers.path(name, variables)
455
457
  end
456
458
 
457
459
  # Generate an absolute URL for a specified named route.
@@ -481,7 +483,7 @@ module Hanami
481
483
  # router.url(:login, return_to: "/dashboard") # => "https://hanamirb.org/login?return_to=%2Fdashboard"
482
484
  # router.url(:framework, name: "router") # => "https://hanamirb.org/router"
483
485
  def url(name, variables = {})
484
- @url_helpers.url(name, variables)
486
+ url_helpers.url(name, variables)
485
487
  end
486
488
 
487
489
  # Recognize the given env, path, or name and return a route for testing
@@ -602,38 +604,23 @@ module Hanami
602
604
  )
603
605
  end
604
606
 
605
- # Returns formatted routes
606
- #
607
- # @return [String] formatted routes
608
- #
609
- # @since 2.0.0
610
- # @api private
611
- def to_inspect
612
- require "hanami/router/inspector"
613
-
614
- inspector = Inspector.new
615
- with(inspector: inspector)
616
-
617
- inspector.call
618
- end
619
-
620
607
  # @since 2.0.0
621
608
  # @api private
622
609
  def fixed(env)
623
- @fixed.dig(env["REQUEST_METHOD"], env["PATH_INFO"])
610
+ @fixed.dig(env[::Rack::REQUEST_METHOD], env[::Rack::PATH_INFO])
624
611
  end
625
612
 
626
613
  # @since 2.0.0
627
614
  # @api private
628
615
  def variable(env)
629
- @variable[env["REQUEST_METHOD"]]&.find(env["PATH_INFO"])
616
+ @variable[env[::Rack::REQUEST_METHOD]]&.find(env[::Rack::PATH_INFO])
630
617
  end
631
618
 
632
619
  # @since 2.0.0
633
620
  # @api private
634
621
  def globbed(env)
635
- @globbed[env["REQUEST_METHOD"]]&.each do |path, to|
636
- if (match = path.match(env["PATH_INFO"]))
622
+ @globbed[env[::Rack::REQUEST_METHOD]]&.each do |path, to|
623
+ if (match = path.match(env[::Rack::PATH_INFO]))
637
624
  return [to, match.named_captures]
638
625
  end
639
626
  end
@@ -645,13 +632,13 @@ module Hanami
645
632
  # @api private
646
633
  def mounted(env)
647
634
  @mounted.each do |prefix, app|
648
- next unless (match = prefix.peek_match(env["PATH_INFO"]))
635
+ next unless (match = prefix.peek_match(env[::Rack::PATH_INFO]))
649
636
 
650
- # TODO: ensure compatibility with existing env["SCRIPT_NAME"]
637
+ # TODO: ensure compatibility with existing env[::Rack::SCRIPT_NAME]
651
638
  # TODO: cleanup this code
652
- env["SCRIPT_NAME"] = env["SCRIPT_NAME"].to_s + prefix.to_s
653
- env["PATH_INFO"] = env["PATH_INFO"].sub(prefix.to_s, "")
654
- env["PATH_INFO"] = "/" if env["PATH_INFO"] == ""
639
+ env[::Rack::SCRIPT_NAME] = env[::Rack::SCRIPT_NAME].to_s + prefix.to_s
640
+ env[::Rack::PATH_INFO] = env[::Rack::PATH_INFO].sub(prefix.to_s, EMPTY_STRING)
641
+ env[::Rack::PATH_INFO] = DEFAULT_PREFIX if env[::Rack::PATH_INFO] == EMPTY_STRING
655
642
 
656
643
  return [app, match.named_captures]
657
644
  end
@@ -663,7 +650,9 @@ module Hanami
663
650
  # @api private
664
651
  def not_allowed(env)
665
652
  (_not_allowed_fixed(env) ||
666
- _not_allowed_variable(env)) and return [405, {"Content-Length" => "11"}, ["Not Allowed"]]
653
+ _not_allowed_variable(env)) and return [HTTP_STATUS_NOT_ALLOWED,
654
+ {::Rack::CONTENT_LENGTH => HTTP_BODY_NOT_ALLOWED_LENGTH},
655
+ [HTTP_BODY_NOT_ALLOWED]]
667
656
  end
668
657
 
669
658
  # @since 2.0.0
@@ -715,6 +704,18 @@ module Hanami
715
704
  # @api private
716
705
  DEFAULT_PREFIX = "/"
717
706
 
707
+ # @since 2.0.0
708
+ # @api private
709
+ PREFIXED_NAME_SEPARATOR = "_"
710
+
711
+ # @since 2.0.0
712
+ # @api private
713
+ ROOT_PATH = "/"
714
+
715
+ # @since 2.0.0
716
+ # @api private
717
+ EMPTY_STRING = ""
718
+
718
719
  # @since 2.0.0
719
720
  # @api private
720
721
  DEFAULT_RESOLVER = ->(_, to) { to }
@@ -723,15 +724,57 @@ module Hanami
723
724
  # @api private
724
725
  DEFAULT_REDIRECT_CODE = 301
725
726
 
727
+ # @since 2.0.0
728
+ # @api private
729
+ HTTP_STATUS_OK = 200
730
+
731
+ # @since 2.0.0
732
+ # @api private
733
+ HTTP_STATUS_NOT_FOUND = 404
734
+
735
+ # @since 2.0.0
736
+ # @api private
737
+ HTTP_BODY_NOT_FOUND = ::Rack::Utils::HTTP_STATUS_CODES.fetch(HTTP_STATUS_NOT_FOUND)
738
+
739
+ # @since 2.0.0
740
+ # @api private
741
+ HTTP_BODY_NOT_FOUND_LENGTH = HTTP_BODY_NOT_FOUND.bytesize.to_s
742
+
743
+ # @since 2.0.0
744
+ # @api private
745
+ HTTP_STATUS_NOT_ALLOWED = 405
746
+
747
+ # @since 2.0.0
748
+ # @api private
749
+ HTTP_BODY_NOT_ALLOWED = ::Rack::Utils::HTTP_STATUS_CODES.fetch(HTTP_STATUS_NOT_ALLOWED)
750
+
751
+ # @since 2.0.0
752
+ # @api private
753
+ HTTP_BODY_NOT_ALLOWED_LENGTH = HTTP_BODY_NOT_ALLOWED.bytesize.to_s
754
+
755
+ # @since 2.0.0
756
+ # @api private
757
+ HTTP_HEADER_LOCATION = "Location"
758
+
726
759
  # @since 2.0.0
727
760
  # @api private
728
761
  PARAMS = "router.params"
729
762
 
763
+ # @since 2.0.0
764
+ # @api private
765
+ ROUTE_VARIABLE_MATCHER = /:/
766
+
767
+ # @since 2.0.0
768
+ # @api private
769
+ ROUTE_GLOBBED_MATCHER = /\*/
770
+
730
771
  # Default response when no route was matched
731
772
  #
732
773
  # @api private
733
774
  # @since 2.0.0
734
- NOT_FOUND = ->(*) { [404, {"Content-Length" => "9"}, ["Not Found"]] }.freeze
775
+ NOT_FOUND = ->(*) {
776
+ [HTTP_STATUS_NOT_FOUND, {::Rack::CONTENT_LENGTH => HTTP_BODY_NOT_FOUND_LENGTH}, [HTTP_BODY_NOT_FOUND]]
777
+ }.freeze
735
778
 
736
779
  # @since 2.0.0
737
780
  # @api private
@@ -746,21 +789,23 @@ module Hanami
746
789
  # @api private
747
790
  def add_route(http_method, path, to, as, constraints, &blk)
748
791
  path = prefixed_path(path)
749
- to = resolve_endpoint(path, to, blk)
792
+ endpoint = resolve_endpoint(path, to, blk)
750
793
 
751
794
  if globbed?(path)
752
- add_globbed_route(http_method, path, to, constraints)
795
+ add_globbed_route(http_method, path, endpoint, constraints)
753
796
  elsif variable?(path)
754
- add_variable_route(http_method, path, to, constraints)
797
+ add_variable_route(http_method, path, endpoint, constraints)
755
798
  else
756
- add_fixed_route(http_method, path, to)
799
+ add_fixed_route(http_method, path, endpoint)
757
800
  end
758
801
 
759
802
  add_named_route(path, as, constraints) if as
760
803
 
761
804
  if inspect?
762
805
  @inspector.add_route(
763
- Route.new(http_method: http_method, path: path, to: to, as: as, constraints: constraints, blk: blk)
806
+ Route.new(
807
+ http_method: http_method, path: path, to: to || endpoint, as: as, constraints: constraints, blk: blk
808
+ )
764
809
  )
765
810
  end
766
811
  end
@@ -804,13 +849,13 @@ module Hanami
804
849
  # @since 2.0.0
805
850
  # @api private
806
851
  def variable?(path)
807
- /:/.match?(path)
852
+ ROUTE_VARIABLE_MATCHER.match?(path)
808
853
  end
809
854
 
810
855
  # @since 2.0.0
811
856
  # @api private
812
857
  def globbed?(path)
813
- /\*/.match?(path)
858
+ ROUTE_GLOBBED_MATCHER.match?(path)
814
859
  end
815
860
 
816
861
  # @since 2.0.0
@@ -828,7 +873,7 @@ module Hanami
828
873
  # @since 2.0.0
829
874
  # @api private
830
875
  def prefixed_name(name)
831
- @name_prefix.relative_join(name, "_").to_sym
876
+ @name_prefix.relative_join(name, PREFIXED_NAME_SEPARATOR).to_sym
832
877
  end
833
878
 
834
879
  # Returns a new instance of Hanami::Router with the modified options.
@@ -855,12 +900,12 @@ module Hanami
855
900
  # @since 2.0.0
856
901
  # @api private
857
902
  def _redirect(to, code)
858
- body = Rack::Utils::HTTP_STATUS_CODES.fetch(code) do
903
+ body = ::Rack::Utils::HTTP_STATUS_CODES.fetch(code) do
859
904
  raise UnknownHTTPStatusCodeError.new(code)
860
905
  end
861
906
 
862
907
  destination = prefixed_path(to)
863
- Redirect.new(destination, code, ->(*) { [code, {"Location" => destination}, [body]] })
908
+ Redirect.new(destination, code, ->(*) { [code, {HTTP_HEADER_LOCATION => destination}, [body]] })
864
909
  end
865
910
 
866
911
  # @since 2.0.0
@@ -868,7 +913,13 @@ module Hanami
868
913
  def _params(env, params)
869
914
  params ||= {}
870
915
  env[PARAMS] ||= {}
871
- env[PARAMS].merge!(Rack::Utils.parse_nested_query(env["QUERY_STRING"]))
916
+
917
+ if (input = env[::Rack::RACK_INPUT]) and input.rewind
918
+ env[PARAMS].merge!(::Rack::Utils.parse_nested_query(input.read))
919
+ input.rewind
920
+ end
921
+
922
+ env[PARAMS].merge!(::Rack::Utils.parse_nested_query(env[::Rack::QUERY_STRING]))
872
923
  env[PARAMS].merge!(params)
873
924
  env[PARAMS] = Params.deep_symbolize(env[PARAMS])
874
925
  env
@@ -882,7 +933,7 @@ module Hanami
882
933
  @fixed.each_value do |routes|
883
934
  break if found
884
935
 
885
- found = routes.key?(env["PATH_INFO"])
936
+ found = routes.key?(env[::Rack::PATH_INFO])
886
937
  end
887
938
 
888
939
  found
@@ -896,7 +947,7 @@ module Hanami
896
947
  @variable.each_value do |routes|
897
948
  break if found
898
949
 
899
- found = routes.find(env["PATH_INFO"])
950
+ found = routes.find(env[::Rack::PATH_INFO])
900
951
  end
901
952
 
902
953
  found
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-router
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.alpha5
4
+ version: 2.0.0.beta2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-04 00:00:00.000000000 Z
11
+ date: 2022-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -118,30 +118,30 @@ dependencies:
118
118
  name: rubocop
119
119
  requirement: !ruby/object:Gem::Requirement
120
120
  requirements:
121
- - - '='
121
+ - - "~>"
122
122
  - !ruby/object:Gem::Version
123
- version: '0.91'
123
+ version: '1.0'
124
124
  type: :development
125
125
  prerelease: false
126
126
  version_requirements: !ruby/object:Gem::Requirement
127
127
  requirements:
128
- - - '='
128
+ - - "~>"
129
129
  - !ruby/object:Gem::Version
130
- version: '0.91'
130
+ version: '1.0'
131
131
  - !ruby/object:Gem::Dependency
132
132
  name: rubocop-performance
133
133
  requirement: !ruby/object:Gem::Requirement
134
134
  requirements:
135
- - - '='
135
+ - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: 1.8.1
137
+ version: '1.0'
138
138
  type: :development
139
139
  prerelease: false
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
- - - '='
142
+ - - "~>"
143
143
  - !ruby/object:Gem::Version
144
- version: 1.8.1
144
+ version: '1.0'
145
145
  description: Rack compatible HTTP router for Ruby
146
146
  email:
147
147
  - me@lucaguidi.com
@@ -162,6 +162,8 @@ files:
162
162
  - lib/hanami/router.rb
163
163
  - lib/hanami/router/block.rb
164
164
  - lib/hanami/router/error.rb
165
+ - lib/hanami/router/formatter/csv.rb
166
+ - lib/hanami/router/formatter/human_friendly.rb
165
167
  - lib/hanami/router/inspector.rb
166
168
  - lib/hanami/router/node.rb
167
169
  - lib/hanami/router/params.rb
@@ -176,7 +178,8 @@ files:
176
178
  homepage: http://hanamirb.org
177
179
  licenses:
178
180
  - MIT
179
- metadata: {}
181
+ metadata:
182
+ rubygems_mfa_required: 'true'
180
183
  post_install_message:
181
184
  rdoc_options: []
182
185
  require_paths:
@@ -185,14 +188,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
185
188
  requirements:
186
189
  - - ">="
187
190
  - !ruby/object:Gem::Version
188
- version: 2.6.0
191
+ version: '3.0'
189
192
  required_rubygems_version: !ruby/object:Gem::Requirement
190
193
  requirements:
191
194
  - - ">"
192
195
  - !ruby/object:Gem::Version
193
196
  version: 1.3.1
194
197
  requirements: []
195
- rubygems_version: 3.2.4
198
+ rubygems_version: 3.3.7
196
199
  signing_key:
197
200
  specification_version: 4
198
201
  summary: Rack compatible HTTP router for Ruby and Hanami