hanami-router 2.0.0.alpha5 → 2.0.0.beta2

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: 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