hanami-router 2.0.0.alpha3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fab23d35a0e2c1e71ec08a112f95f35a2c21eed5fb3ab45f231a2a7fc500cc31
4
- data.tar.gz: 85c7e6ab36e321fb04235f088f3f479f542e98cf00e5ae7d642bb323bb42d969
3
+ metadata.gz: d1d74dfb9252f6462cb018bd567261aad94f83ea6837bb78f3d597dd9b62d0c5
4
+ data.tar.gz: 30c7f9425d0ad82d0c3059ed8a2d8fcc5e1a1a11092caf5f725338748451fddc
5
5
  SHA512:
6
- metadata.gz: 2ce90e7659b29b0571742eb972442ea27a4d51d1ea5500f9d25f943fe7e6a5e9b04598a1289a4c50f107289ea7162708a78e4825564b4ef056ee30a5765a63d6
7
- data.tar.gz: b953c5d251e8cfb6f698bb6cea77df0dec2ff194bf51fe091d7fb4464ffad135c0760d328f9e50ae49f6cd48c45171b6ef4c55dc42f64c924cfd6d631cde5250
6
+ metadata.gz: 1f351789e9d4f24ef65cfdb6e19868e56c612b2f222dfd2f250f15bddfdcf00fb9d7146a5b4bd978fa2cf5b067b2dc1a96f9cf0430f028240a4c6543075cd0a1
7
+ data.tar.gz: 7019f2ef7c57177041495e7614992b117548d5d0eeace16d4784a9dc07b678d1d49e0987a6f750fd51b342cd5b86136fe393cef2d1fa126250a07ff8887bc1fe
data/CHANGELOG.md CHANGED
@@ -1,29 +1,103 @@
1
1
  # Hanami::Router
2
+
2
3
  Rack compatible HTTP router for Ruby
3
4
 
5
+ ## v2.0.0 - 2022-11-22
6
+
7
+ ### Fixed
8
+
9
+ - [Luca Guidi] Don't parse request body when Body Parser already parsed it
10
+
11
+ ## v2.0.0.rc1 - 2022-11-08
12
+
13
+ ### Fixed
14
+
15
+ - [Luca Guidi] During routes inspection, ensure to print path prefixes for nested named routes
16
+
17
+ ### Changed
18
+
19
+ - [Benjamin Klotz] `Hanami::Middleware::BodyParser::Parser#parse` (abstract method) to raise `NoMethodError` instead of `NotImplementedError`
20
+
21
+ ## v2.0.0.beta4 - 2022-10-24
22
+
23
+ ### Changed
24
+
25
+ - [Peter Solnica] `Hanami::Middleware::BodyParser` can be initialized with one or more formats and additional custom mime types per format (`Hanami::Middleware::BodyParser.new(app, [:json, :xml])` or `Hanami::Middleware::BodyParser.new(app, [json: "application/json+scim"])`) (#230)
26
+
27
+ ## v2.0.0.beta2 - 2022-08-16
28
+
29
+ ### Fixed
30
+
31
+ - [Luca Guidi] [Internal] Ensure `Hanami::Middleware::Error` class is available where it is needed [#225]
32
+
33
+ ## v2.0.0.beta1 - 2022-07-20
34
+
35
+ ### Added
36
+
37
+ - [Marc Busqué] Introduced `Hanami::Router::Formatter::CSV` for CSV inspection of the routes
38
+
39
+ ### Fixed
40
+
41
+ - [Marc Busqué] Routes inspection: Don't print empty line after the definition of a `get` route
42
+ - [Marc Busqué] Routes inspection: Print `<controller>.<action>` instead of `(proc)`
43
+ - [Marc Busqué] Routes inspection: Print `(block)` instead of `NilClass` when inspecting a route block
44
+
45
+ ## v2.0.0.alpha6 - 2022-02-10
46
+
47
+ ### Added
48
+
49
+ - [Luca Guidi] Official support for MRI 3.1
50
+ - [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`
51
+
52
+ ### Changed
53
+
54
+ - [Luca Guidi] Drop support for Ruby: MRI 2.6, and 2.7.
55
+
56
+ ## v2.0.0.alpha5 - 2021-05-04
57
+
58
+ ### Added
59
+
60
+ - [Luca Guidi] Introduced `Hanami::Router#to_inspect` which returns a string blob with all the routes formatted for human readability
61
+
62
+ ## v2.0.0.alpha4 - 2021-01-16
63
+
64
+ ### Added
65
+
66
+ - [Luca Guidi] Official support for MRI 3.0
67
+ - [Luca Guidi] Introduced `Hanami::Middleware::BodyParser::Parser` as superclass for body parsers
68
+ - [Paweł Świątkowski] Added `not_found:` option to `Hanami::Router#initialize` to customize HTTP 404 status
69
+
4
70
  ## v2.0.0.alpha3 - 2020-05-20
71
+
5
72
  ### Fixed
73
+
6
74
  - [Luca Guidi] `Hanami::Router#initialize` do not yield block if not given
7
75
  - [Luca Guidi] Ensure to not accidentally cache response headers for HTTP 404 and 405
8
76
  - [Luca Guidi] Ensure scoped root to not be added as trailing slash
9
77
 
10
78
  ## v2.0.0.alpha2 - 2020-02-19
79
+
11
80
  ### Added
81
+
12
82
  - [Luca Guidi] Block syntax. Routes definition accept a block which returning value is the body of the Rack response.
13
83
  - [Luca Guidi] Added `resolver:` option to `Hanami::Router#initialize` to provide your own strategy to load endpoints.
14
84
 
15
85
  ### Changed
86
+
16
87
  - [Luca Guidi] Removed `Hanami::Router#resource` and `#resources`.
17
88
  - [Luca Guidi] Removed loading of routes endpoints.
18
89
  - [Luca Guidi] Removed `inflector:` from `Hanami::Router#initialize`
19
90
  - [Luca Guidi] Removed `scheme:`, `host:`, `port:` from `Hanami::Router#initialize`, use `base_url:` instead.
20
91
 
21
92
  ## v2.0.0.alpha1 - 2019-01-30
93
+
22
94
  ### Added
95
+
23
96
  - [Luca Guidi] Introduce `Hanami::Router#scope` to support single routing tier for Hanami
24
97
  - [Semyon Pupkov] Added `inflector:` option for `Hanami::Router#initialize` based on `dry-inflector`
25
98
 
26
99
  ### Changed
100
+
27
101
  - [Luca Guidi] Drop support for Ruby: MRI 2.3, and 2.4.
28
102
  - [Luca Guidi] Renamed `Hanami::Router#namespace` => `#prefix`
29
103
  - [Gustavo Caso] Remove body cleanup for `HEAD` requests
@@ -35,25 +109,34 @@ Rack compatible HTTP router for Ruby
35
109
  - [Luca Guidi] `Hanami::Router#initialize` requires `configuration:` option if routes endpoints are `Hanami::Action` subclasses
36
110
 
37
111
  ## v1.3.2 - 2019-02-13
112
+
38
113
  ### Added
114
+
39
115
  - [Luca Guidi] Official support for Ruby: MRI 2.7
40
116
  - [Luca Guidi] Support `rack` 2.1
41
117
 
42
118
  ## v1.3.1 - 2019-01-18
119
+
43
120
  ### Added
121
+
44
122
  - [Luca Guidi] Official support for Ruby: MRI 2.6
45
123
  - [Luca Guidi] Support `bundler` 2.0+
46
124
 
47
125
  ## v1.3.0 - 2018-10-24
126
+
48
127
  ### Fixed
128
+
49
129
  - [Tim Riley] Skip attempting to parse unknown types in `Hanami::Middleware::BodyParser`
50
130
 
51
131
  ## v1.3.0.beta1 - 2018-08-08
132
+
52
133
  ### Added
134
+
53
135
  - [Luca Guidi] Official support for JRuby 9.2.0.0
54
136
  - [Gustavo Caso] Introduce `Hanami::Middleware::BodyParser` Rack middleware to parse payload of non-GET HTTP requests.
55
137
 
56
138
  ### Deprecated
139
+
57
140
  - [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.
58
141
  - [Gustavo Caso] Deprecate `Hanami::Router.new(body_parsers: [:json])`. Use `Hanami::Middleware::BodyParser` instead.
59
142
 
@@ -68,16 +151,21 @@ Rack compatible HTTP router for Ruby
68
151
  ## v1.2.0.beta1 - 2018-02-28
69
152
 
70
153
  ## v1.1.1 - 2018-02-27
154
+
71
155
  ### Added
156
+
72
157
  - [Luca Guidi] Official support for Ruby: MRI 2.5
73
158
 
74
159
  ### Fixed
160
+
75
161
  - [malin-as] Ensure `Hanami::Router` to properly respond to `unlink`
76
162
 
77
163
  ## v1.1.0 - 2017-10-25
78
164
 
79
165
  ## v1.1.0.rc1 - 2017-10-16
166
+
80
167
  ### Added
168
+
81
169
  - [Sergey Fedorov] Allow Rack applications to be mounted inside a namespace. (`namespace "api" { mount V1::App, at: "/v1" }`)
82
170
 
83
171
  ## v1.1.0.beta3 - 2017-10-04
@@ -87,10 +175,13 @@ Rack compatible HTTP router for Ruby
87
175
  ## v1.1.0.beta1 - 2017-08-11
88
176
 
89
177
  ## v1.0.1 - 2017-07-10
178
+
90
179
  ### Added
180
+
91
181
  - [Luca Guidi] Introduce new introspection methods (`#redirect?` and `#redirection_path`) for recognized routes (see `Hanami::Router#recognize`)
92
182
 
93
183
  ### Fixed
184
+
94
185
  - [Luca Guidi] Ensure `Hanami::Router#redirect` to be compatible with `#recognize`
95
186
 
96
187
  ## v1.0.0 - 2017-04-06
@@ -100,131 +191,176 @@ Rack compatible HTTP router for Ruby
100
191
  ## v1.0.0.beta3 - 2017-03-17
101
192
 
102
193
  ## v1.0.0.beta2 - 2017-03-02
194
+
103
195
  ### Fixed
196
+
104
197
  - [Valentyn Ostakh] Deep symbolize params from parsed body
105
198
  - [Luca Guidi] `Hanami::Router#recognize` must return a non-routeable object when the endpoint cannot be resolved
106
199
 
107
200
  ## v1.0.0.beta1 - 2017-02-14
201
+
108
202
  ### Added
203
+
109
204
  - [Luca Guidi] Official support for Ruby: MRI 2.4
110
205
  - [Jakub Pavlík] Added `:as` option for RESTful resources (eg. `resources :psi, controller: 'dogs', as: 'dogs'`)
111
206
 
112
207
  ### Changed
208
+
113
209
  - [Pascal Betz] Make compatible with Rack 2.0 only
114
210
 
115
211
  ## v0.8.1 - 2016-11-18
212
+
116
213
  ### Fixed
214
+
117
215
  - [Luca Guidi] Ensure JSON body parser to not eval untrusted input
118
216
 
119
217
  ## v0.8.0 - 2016-11-15
218
+
120
219
  ### Added
220
+
121
221
  - [Kyle Chong] Referenced params from body parses in Rack env via `router.parsed_body`
122
222
 
123
223
  ### Fixed
224
+
124
225
  - [Luca Guidi & Lucas Hosseini] Ensure params from routes take precedence over params from body parsing
125
226
  - [Luca Guidi] Ensure inspector to respect path prefix of mouted apps
126
227
 
127
228
  ### Changed
229
+
128
230
  - [Luca Guidi] Official support for Ruby: MRI 2.3+ and JRuby 9.1.5.0+
129
231
 
130
232
  ## v0.7.0 - 2016-07-22
233
+
131
234
  ### Added
235
+
132
236
  - [Sean Collins] Introduced `Hanami::Router#root`. Example: `root to: 'home#index'`, equivalent to `get '/', to: 'home#index', as: :root`.
133
237
  - [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`
134
238
  - [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`.
135
239
  - [Luca Guidi] Introduced `Hanami::Routing::RecognizedRoute#path` in order to allow a better introspection
136
240
 
137
241
  ### Fixed
242
+
138
243
  - [Andrew De Ponte] Make routes inspection to work when non-Hanami apps are mounted
139
244
  - [Andrew De Ponte] Ensure to set the right `SCRIPT_NAME` in Rack env for mounted Hanami apps
140
245
  - [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
141
246
 
142
247
  ### Changed
248
+
143
249
  – [Luca Guidi] Drop support for Ruby 2.0 and 2.1. Official support for JRuby 9.0.5.0+
144
250
 
145
251
  ## v0.6.2 - 2016-02-05
252
+
146
253
  ### Fixed
254
+
147
255
  - [Anton Davydov] Fix double leading slash for Capybara's `current_path`
148
256
 
149
257
  ## v0.6.1 - 2016-01-27
258
+
150
259
  ### Fixed
260
+
151
261
  - [Luca Guidi] Fix body parsers for non Hash requests
152
262
 
153
263
  ## v0.6.0 - 2016-01-22
264
+
154
265
  ### Changed
266
+
155
267
  - [Luca Guidi] Renamed the project
156
268
 
157
269
  ## v0.5.1 - 2016-01-19
270
+
158
271
  - [Anton Davydov] Print stacked lines for routes inspection
159
272
 
160
273
  ## v0.5.0 - 2016-01-12
274
+
161
275
  ### Added
276
+
162
277
  - [Luca Guidi] Added `Lotus::Router#recognize` as a testing facility. Example `router.recognize('/') # => associated route`
163
278
  - [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
164
279
  - [David Strauß] Make `Lotus::Routing::Parsing::JsonParser` compatible with `application/vnd.api+json` MIME Type
165
280
  - [Alfonso Uceda Pompa] Improved exception messages for `Lotus::Router#path` and `#url`
166
281
 
167
282
  ### Fixed
283
+
168
284
  - [Alfonso Uceda Pompa] Ensure `Lotus::Router#path` and `#url` to generate correct URL for mounted applications
169
285
  - [Vladislav Zarakovsky] Ensure Force SSL mode to respect Rack SPEC
170
286
 
171
287
  ### Changed
288
+
172
289
  - [Alfonso Uceda Pompa] A failure for body parsers raises a `Lotus::Routing::Parsing::BodyParsingError` exception
173
290
  - [Karim Tarek] Introduced `Lotus::Router::Error` and let all the framework exceptions to inherit from it.
174
291
 
175
292
  ## v0.4.3 - 2015-09-30
293
+
176
294
  ### Added
295
+
177
296
  - [Luca Guidi] Official support for JRuby 9k+
178
297
 
179
298
  ## v0.4.2 - 2015-07-10
299
+
180
300
  ### Fixed
301
+
181
302
  - [Alfonso Uceda Pompa] Ensure mounted applications to not repeat their prefix (eg `/admin/admin`)
182
303
  - [Thiago Felippe] Ensure router inspector properly prints routes with repeated entries (eg `/admin/dashboard/admin`)
183
304
 
184
305
  ## v0.4.1 - 2015-06-23
306
+
185
307
  ### Added
308
+
186
309
  - [Alfonso Uceda Pompa] Force SSL (eg `Lotus::Router.new(force_ssl: true`).
187
310
  - [Alfonso Uceda Pompa] Allow router to accept a `:prefix` option, in order to generate prefixed routes.
188
311
 
189
312
  ## v0.4.0 - 2015-05-15
313
+
190
314
  ### Added
315
+
191
316
  - [Alfonso Uceda Pompa] Nested RESTful resource(s)
192
317
 
193
318
  ### Changed
319
+
194
320
  - [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`)
195
321
 
196
322
  ## v0.3.0 - 2015-03-23
197
323
 
198
324
  ## v0.2.1 - 2015-01-30
325
+
199
326
  ### Added
327
+
200
328
  - [Alfonso Uceda Pompa] Lotus::Action compat: invoke `.call` if defined, otherwise fall back to `#call`.
201
329
 
202
330
  ## v0.2.0 - 2014-12-23
331
+
203
332
  ### Added
333
+
204
334
  - [Luca Guidi & Alfonso Uceda Pompa] Introduced routes inspector for CLI
205
335
  - [Luca Guidi & Janko Marohnić] Introduced body parser for JSON
206
336
  - [Luca Guidi] Introduced request body parsers: they parse body and turn into params.
207
337
  - [Fred Wu] Introduced Router#define
208
338
 
209
339
  ### Fixed
340
+
210
341
  - [Luca Guidi] Fix for member/collection actions in RESTful resource(s): allow to take actions with a leading slash.
211
342
  - [Janko Marohnić] Fix for nested namespaces and RESTful resource(s) under namespace. They were generating wrong route names.
212
343
  - [Luca Guidi] Made InvalidRouteException to inherit from StandardError so it can be catched from anonymous `rescue` clause
213
344
  - [Luca Guidi] Fix RESTful resource(s) to respect :only/:except options
214
345
 
215
346
  ### Changed
347
+
216
348
  - [Luca Guidi] Aligned naming conventions with Lotus::Controller: no more BooksController::Index. Use Books::Index instead.
217
349
  - [Luca Guidi] Removed `:prefix` option for routes. Use `#namespace` blocks instead.
218
350
  - [Janko Marohnić] Make 301 the default redirect status
219
351
 
220
352
  ## v0.1.1 - 2014-06-23
353
+
221
354
  ### Added
355
+
222
356
  - [Luca Guidi] Introduced Lotus::Router#mount
223
357
  - [Luca Guidi] Let specify a pattern for Lotus::Routing::EndpointResolver
224
358
  - [Luca Guidi] Make Lotus::Routing::Endpoint::EndpointNotFound to inherit from StandardError, instead of Exception. This make it compatible with Rack::ShowExceptions.
225
359
 
226
360
  ## v0.1.0 - 2014-01-23
361
+
227
362
  ### Added
363
+
228
364
  - [Luca Guidi] Official support for Ruby 2.1
229
365
  - [Luca Guidi] Added support for OPTIONS HTTP verb
230
366
  - [Luca Guidi] Added Lotus::Routing::EndpointNotFound when a lazy endpoint can't be found
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright © 2014-2017 Luca Guidi
1
+ Copyright © 2014-2021 Luca Guidi
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -2,12 +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
- [![Build Status](https://ci.hanamirb.org/api/badges/hanami/router/status.svg)](https://ci.hanamirb.org/hanami/router)
9
- [![CircleCI](https://circleci.com/gh/hanami/router/tree/master.svg?style=svg)](https://circleci.com/gh/hanami/router/tree/master)
10
- [![Test Coverage](https://codecov.io/gh/hanami/router/branch/master/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)
11
14
  [![Depfu](https://badges.depfu.com/badges/5f6b8e8fa3b0d082539f0b0f84d55960/overview.svg)](https://depfu.com/github/hanami/router?project=Bundler)
12
15
  [![Inline Docs](http://inch-ci.org/github/hanami/router.svg)](http://inch-ci.org/github/hanami/router)
13
16
 
@@ -22,7 +25,7 @@ Rack compatible, lightweight and fast HTTP Router for Ruby and [Hanami](http://h
22
25
 
23
26
  ## Rubies
24
27
 
25
- __Hanami::Router__ supports Ruby (MRI) 2.5+
28
+ __Hanami::Router__ supports Ruby (MRI) 3.0+
26
29
 
27
30
 
28
31
  ## Installation
@@ -225,6 +228,13 @@ router = Hanami::Router.new
225
228
  router.call(Rack::MockRequest.env_for("/unknown")).status # => 404
226
229
  ```
227
230
 
231
+ ### Explicit Not Found:
232
+
233
+ ```ruby
234
+ router = Hanami::Router.new(not_found: ->(_) { [499, {}, []]})
235
+ router.call(Rack::MockRequest.env_for("/unknown")).status # => 499
236
+ ```
237
+
228
238
  ### Body Parsers
229
239
 
230
240
  Rack ignores request bodies unless they come from a form submission.
@@ -355,6 +365,4 @@ __Hanami::Router__ uses [Semantic Versioning 2.0.0](http://semver.org)
355
365
 
356
366
  ## Copyright
357
367
 
358
- Copyright © 2014-2020 Luca Guidi – Released under MIT License
359
-
360
- This project was formerly known as Lotus (`lotus-router`).
368
+ Copyright © 2014-2022 Hanami Team – Released under MIT License
@@ -14,11 +14,11 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = "http://hanamirb.org"
15
15
  spec.license = "MIT"
16
16
 
17
- spec.files = `git ls-files -- lib/* CHANGELOG.md LICENSE.md README.md hanami-router.gemspec`.split($INPUT_RECORD_SEPARATOR)
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.5.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"
@@ -28,4 +28,7 @@ Gem::Specification.new do |spec|
28
28
  spec.add_development_dependency "rake", "~> 13"
29
29
  spec.add_development_dependency "rack-test", "~> 1.0"
30
30
  spec.add_development_dependency "rspec", "~> 3.8"
31
+
32
+ spec.add_development_dependency "rubocop", "~> 1.0"
33
+ spec.add_development_dependency "rubocop-performance", "~> 1.0"
31
34
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack/builder"
4
+ require_relative "./trie"
5
+
6
+ module Hanami
7
+ module Middleware
8
+ # Hanami Rack middleware stack
9
+
10
+ # @since 2.0.0
11
+ # @api private
12
+ class App
13
+ # @param router [Hanami::Router]
14
+ # @param mapping [Hash]
15
+ #
16
+ # @since 2.0.0
17
+ # @api private
18
+ def initialize(router, mapping)
19
+ @trie = Hanami::Middleware::Trie.new(router)
20
+
21
+ mapping.each do |path, stack|
22
+ builder = Rack::Builder.new
23
+
24
+ stack.each do |middleware, args, blk|
25
+ builder.use(middleware, *args, &blk)
26
+ end
27
+
28
+ builder.run(router)
29
+
30
+ @trie.add(path, builder.to_app.freeze)
31
+ end
32
+
33
+ @trie.freeze
34
+ @inspector = router.inspector.freeze
35
+ end
36
+
37
+ # @since 2.0.0
38
+ # @api private
39
+ def call(env)
40
+ @trie.find(env[::Rack::PATH_INFO]).call(env)
41
+ end
42
+
43
+ # @since 2.0.0
44
+ # @api private
45
+ def to_inspect
46
+ @inspector&.call.to_s
47
+ end
48
+ end
49
+ end
50
+ end
@@ -9,15 +9,38 @@ module Hanami
9
9
  # @api private
10
10
  # @since 1.3.0
11
11
  module ClassInterface
12
+ # Instantiate a new body parser instance and load its parsers
13
+ #
14
+ # @example
15
+ # Hanami::Middleware::BodyParser.new(->(env) { [200, {}, "app"] }, :json)
16
+ #
17
+ # Hanami::Middleware::BodyParser.new(
18
+ # ->(env) { [200, {}, "app"] }, [json: "application/json+scim"]
19
+ # )
20
+ #
21
+ # Hanami::Middleware::BodyParser.new(
22
+ # ->(env) { [200, {}, "app"] }, [json: ["application/json+scim", "application/ld+json"]]
23
+ # )
24
+ #
25
+ # @param app [#call]
26
+ # @param parser_specs [Symbol, Array<Hash>] parser name or name with mime-type(s)
27
+ #
28
+ # @api private
29
+ # @since 2.0.0
30
+ # @return BodyParser
31
+ def new(app, parser_specs)
32
+ super(app, build_parsers(parser_specs))
33
+ end
34
+
12
35
  # @api private
13
36
  # @since 1.3.0
14
- def for(parser) # rubocop:disable Metrics/MethodLength
37
+ def build(parser, **config)
15
38
  parser =
16
39
  case parser
17
40
  when String, Symbol
18
- require_parser(parser)
41
+ build(parser_class(parser), **config)
19
42
  when Class
20
- parser.new
43
+ parser.new(**config)
21
44
  else
22
45
  parser
23
46
  end
@@ -27,32 +50,76 @@ module Hanami
27
50
  parser
28
51
  end
29
52
 
53
+ # @api private
54
+ # @since 2.0.0
55
+ def build_parsers(parser_specs, registry = {})
56
+ return DEFAULT_BODY_PARSERS if parser_specs.empty?
57
+
58
+ parsers = Array(parser_specs).flatten(0)
59
+
60
+ parsers.each_with_object(registry) do |spec, memo|
61
+ if spec.is_a?(Hash) && spec.size > 1
62
+ spec.each do |key, value|
63
+ build_parsers([key => [value]], memo)
64
+ end
65
+ else
66
+ name, *mime_types = Array(*spec).flatten(0)
67
+
68
+ parser = build(name, mime_types: mime_types.flatten)
69
+
70
+ parser.mime_types.each do |mime|
71
+ memo[mime] = parser
72
+ end
73
+ end
74
+ end
75
+ end
76
+
30
77
  private
31
78
 
32
79
  # @api private
33
80
  # @since 1.3.0
34
81
  PARSER_METHODS = %i[mime_types parse].freeze
35
82
 
83
+ # @api private
84
+ # @since 2.0.0
85
+ DEFAULT_BODY_PARSERS = {}.freeze
86
+
36
87
  # @api private
37
88
  # @since 1.3.0
38
89
  def ensure_parser(parser)
39
- raise InvalidParserError.new(parser) unless PARSER_METHODS.all? { |method| parser.respond_to?(method) }
90
+ unless PARSER_METHODS.all? { |method| parser.respond_to?(method) }
91
+ raise InvalidParserError.new(parser)
92
+ end
40
93
  end
41
94
 
42
95
  # @api private
43
96
  # @since 1.3.0
44
- def require_parser(parser)
45
- require "hanami/middleware/body_parser/#{parser}_parser"
97
+ # rubocop:disable Lint/SuppressedException
98
+ def parser_class(parser_name)
99
+ parser = nil
100
+
101
+ begin
102
+ require "hanami/middleware/body_parser/#{parser_name}_parser"
103
+ rescue LoadError; end
104
+
105
+ begin
106
+ parser = load_parser!("#{classify(parser_name)}Parser")
107
+ rescue NameError; end
46
108
 
47
- load_parser!("#{classify(parser)}Parser").new
48
- rescue LoadError, NameError
49
- raise UnknownParserError.new(parser)
109
+ parser
110
+ ensure
111
+ raise UnknownParserError, parser_name unless parser
50
112
  end
113
+ # rubocop:enable Lint/SuppressedException
51
114
 
115
+ # @api private
116
+ # @since 1.3.0
52
117
  def classify(parser)
53
118
  parser.to_s.split(/_/).map(&:capitalize).join
54
119
  end
55
120
 
121
+ # @api private
122
+ # @since 1.3.0
56
123
  def load_parser!(class_name)
57
124
  Hanami::Middleware::BodyParser.const_get(class_name, false)
58
125
  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
@@ -1,17 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "json"
4
- require_relative "errors"
4
+ require_relative "parser"
5
5
 
6
6
  module Hanami
7
7
  module Middleware
8
8
  class BodyParser
9
9
  # @since 1.3.0
10
10
  # @api private
11
- class JsonParser
11
+ class JsonParser < Parser
12
12
  # @since 1.3.0
13
13
  # @api private
14
- def mime_types
14
+ def self.mime_types
15
15
  ["application/json", "application/vnd.api+json"]
16
16
  end
17
17