hanami-router 2.2.0 → 2.3.0.beta1

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: 5bba2b56b3f4ddbedc47b2d21189f7e88ce172505dabbdca6c6d6266aa6c7fa2
4
- data.tar.gz: d601d610fb2cacbef79ca4770ab1e63869a5469ac46671c823e106086c0e58d0
3
+ metadata.gz: dd6e74eeead3378e5b8697f4a3d6ff3883a71c140ace0699a9bb30aa2b3f303d
4
+ data.tar.gz: dd4a259ce71090ed517152b0203896274c25d893afaf68768a118c1c77300c53
5
5
  SHA512:
6
- metadata.gz: 88b44cc6c09c227aaf45352a49344a48530c4095fa1ac2f53ed0bf38e7901876805121c1090d24759420c8ad0029fbc9aba43d383adb93635161ce3cfb8fe321
7
- data.tar.gz: 319831eb561257e58afbc2479447e92862b452424a44c1efffc8f534d4bfc40f2549e70d0849ef4e303182f7d8ec620ad8a6d55a25f9e3994a20215c3dd89bf8
6
+ metadata.gz: cd35252d98f215ec28a0676a3a36db818af56b78d3e46b84f2e02bff14a9e49422c6fd89b4a3f6313929f3cbaedd2f193b9f35dd15b7c03b5a1252405f424e8d
7
+ data.tar.gz: 23f275b9f2fbd71d68453e69c00983f9729e98fd3b16e3b51866bfb27b73dab0678d7c204e7ba63d6b9d24dc5a5f1e1f91b88567ee0ec315c5bc1fd2669ae9fb
data/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  Rack compatible HTTP router for Ruby
4
4
 
5
+ ## v2.3.0.beta1 - 2025-10-03
6
+
7
+ ### Changed
8
+
9
+ - [Kyle Plump, Tim Riley] Support Rack 3 in addition to Rack 2 (#277)
10
+ - [Sven Schwyn] Convert -, +, ~, and . to underscore in URL helper names (#280)
11
+ - [inouire] Allow redirects to absolute URLs: `redirect "/redirect", to: "https://hanamirb.org/"` (#282)
12
+
5
13
  ## v2.2.0 - 2024-11-05
6
14
 
7
15
  ### Changed
data/README.md CHANGED
@@ -157,6 +157,8 @@ end
157
157
  Hanami::Router.new do
158
158
  get "/redirect_destination", to: ->(env) { [200, {}, ["Redirect destination!"]] }
159
159
  redirect "/legacy", to: "/redirect_destination"
160
+ redirect "/learn-more", to: "https://hanamirb.org/"
161
+ redirect "/chat", to: URI("xmpp://myapp.net/")
160
162
  end
161
163
  ```
162
164
 
@@ -349,12 +351,17 @@ __Hanami::Router__ uses [Semantic Versioning 2.0.0](http://semver.org)
349
351
 
350
352
  ## Contributing
351
353
 
352
- 1. Fork it
354
+ 1. Fork this repo to your account and clone it locally (`git clone git@github.com:your-pseudo/your-cloned-repo.git`)
353
355
  2. Create your feature branch (`git checkout -b my-new-feature`)
354
- 3. Commit your changes (`git commit -am 'Add some feature'`)
355
- 4. Push to the branch (`git push origin my-new-feature`)
356
- 5. Create new Pull Request
356
+ 3. Install the dependencies (`bundle install`)
357
+ 4. Run tests, they should all pass (`./script/ci`)
358
+ 5. Make your changes & check that the tests still pass. Add some test cases if needed.
359
+ 6. Commit your changes (`git commit -am 'Add some feature'`)
360
+ 7. Push to the branch (`git push origin my-new-feature`)
361
+ 8. Create new Pull Request on Github with some context on what you're trying to fix or to improve with this contribution
362
+
363
+ Thank you for contributing!
357
364
 
358
365
  ## Copyright
359
366
 
360
- Copyright © 2014–2024 Hanami Team – Released under MIT License
367
+ Copyright © 2014–2025 Hanami Team – Released under MIT License
@@ -20,13 +20,14 @@ Gem::Specification.new do |spec|
20
20
  spec.metadata["rubygems_mfa_required"] = "true"
21
21
  spec.required_ruby_version = ">= 3.1"
22
22
 
23
- spec.add_dependency "rack", "~> 2.0"
23
+ spec.add_dependency "rack", ">= 2.0"
24
24
  spec.add_dependency "mustermann", "~> 3.0"
25
25
  spec.add_dependency "mustermann-contrib", "~> 3.0"
26
+ spec.add_dependency "csv", "~> 3.3"
26
27
 
27
28
  spec.add_development_dependency "bundler", ">= 1.6", "< 3"
28
29
  spec.add_development_dependency "rake", "~> 13"
29
- spec.add_development_dependency "rack-test", "~> 1.0"
30
+ spec.add_development_dependency "rack-test", "~> 2.0"
30
31
  spec.add_development_dependency "rspec", "~> 3.8"
31
32
 
32
33
  spec.add_development_dependency "rubocop", "~> 1.0"
@@ -100,11 +100,13 @@ module Hanami
100
100
 
101
101
  begin
102
102
  require "hanami/middleware/body_parser/#{parser_name}_parser"
103
- rescue LoadError; end
103
+ rescue LoadError
104
+ end
104
105
 
105
106
  begin
106
107
  parser = load_parser!("#{classify(parser_name)}Parser")
107
- rescue NameError; end
108
+ rescue NameError
109
+ end
108
110
 
109
111
  parser
110
112
  ensure
@@ -30,6 +30,8 @@ module Hanami
30
30
  # @since 2.0.1
31
31
  # @api private
32
32
  def parse(*, env)
33
+ # Rewind to ensure successful parsing (required for Rack 3's `.parse_multipart`).
34
+ env[::Rack::RACK_INPUT].rewind if env[::Rack::RACK_INPUT].respond_to?(:rewind)
33
35
  ::Rack::Multipart.parse_multipart(env)
34
36
  rescue StandardError => exception
35
37
  raise BodyParsingError.new(exception.message)
@@ -39,10 +39,11 @@ module Hanami
39
39
  end
40
40
 
41
41
  def call(env)
42
- body = env[RACK_INPUT].read
43
- return @app.call(env) if body.empty?
42
+ body = env[RACK_INPUT]&.read
43
+ return @app.call(env) if body.nil? || body.empty?
44
44
 
45
- env[RACK_INPUT].rewind # somebody might try to read this stream
45
+ # Somebody might try to read this stream
46
+ Rack::RewindableInput.new(env[RACK_INPUT]).rewind
46
47
 
47
48
  if (parser = @parsers[media_type(env)])
48
49
  env[Router::ROUTER_PARSED_BODY] = parser.parse(body, env)
@@ -66,6 +66,7 @@ module Hanami
66
66
  # @since 2.0.0
67
67
  def call
68
68
  body = instance_exec(&@blk)
69
+
69
70
  [status, headers, [body]]
70
71
  end
71
72
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hanami
4
+ class Router
5
+ # @since 2.2.0
6
+ # @api private
7
+ def self.rack_3?
8
+ defined?(Rack::Headers)
9
+ end
10
+ end
11
+ end
@@ -8,6 +8,6 @@ module Hanami
8
8
  #
9
9
  # @since 0.1.0
10
10
  # @api public
11
- VERSION = "2.2.0"
11
+ VERSION = "2.3.0.beta1"
12
12
  end
13
13
  end
data/lib/hanami/router.rb CHANGED
@@ -22,6 +22,7 @@ module Hanami
22
22
  require "hanami/router/url_helpers"
23
23
  require "hanami/router/globbed_path"
24
24
  require "hanami/router/mounted_path"
25
+ require "hanami/router/rack_utils"
25
26
 
26
27
  # URL helpers for other Hanami integrations
27
28
  #
@@ -106,6 +107,14 @@ module Hanami
106
107
  return not_allowed(env) || not_found(env)
107
108
  end
108
109
 
110
+ # Rack 3 no longer requires "rack.input" to be rewindable. Force input to be
111
+ # rewindable to maintain Rack 2 behavior.
112
+ #
113
+ # @since 2.2.0
114
+ if Hanami::Router.rack_3? && env[::Rack::RACK_INPUT]
115
+ env[::Rack::RACK_INPUT] = Rack::RewindableInput.new(env[::Rack::RACK_INPUT])
116
+ end
117
+
109
118
  endpoint.call(
110
119
  _params(env, params)
111
120
  ).to_a
@@ -693,6 +702,10 @@ module Hanami
693
702
  # @api private
694
703
  PREFIXED_NAME_SEPARATOR = "_"
695
704
 
705
+ # @since x.x.x
706
+ # @api private
707
+ UNDERSCORED_NAME_REGEXP = /[-+~.]/
708
+
696
709
  # @since 2.0.0
697
710
  # @api private
698
711
  ROOT_PATH = "/"
@@ -739,7 +752,11 @@ module Hanami
739
752
 
740
753
  # @since 2.0.0
741
754
  # @api private
742
- HTTP_HEADER_LOCATION = "Location"
755
+ HTTP_HEADER_LOCATION = Hanami::Router.rack_3? ? "location" : "Location"
756
+
757
+ # @since 2.2.0
758
+ # @api private
759
+ HTTP_HEADER_ALLOW = Hanami::Router.rack_3? ? "allow" : "Allow"
743
760
 
744
761
  # @since 2.0.0
745
762
  # @api private
@@ -762,7 +779,7 @@ module Hanami
762
779
  HTTP_STATUS_NOT_ALLOWED,
763
780
  {
764
781
  ::Rack::CONTENT_LENGTH => HTTP_BODY_NOT_ALLOWED_LENGTH,
765
- "Allow" => allowed_http_methods.join(", ")
782
+ HTTP_HEADER_ALLOW => allowed_http_methods.join(", ")
766
783
  },
767
784
  [HTTP_BODY_NOT_ALLOWED]
768
785
  ]
@@ -774,12 +791,13 @@ module Hanami
774
791
  # @since 2.0.0
775
792
  NOT_FOUND = ->(*) {
776
793
  [HTTP_STATUS_NOT_FOUND, {::Rack::CONTENT_LENGTH => HTTP_BODY_NOT_FOUND_LENGTH}, [HTTP_BODY_NOT_FOUND]]
777
- }.freeze
794
+ }
778
795
 
779
796
  # @since 2.0.0
780
797
  # @api private
781
798
  def lookup(env)
782
799
  endpoint = fixed(env)
800
+
783
801
  return [endpoint, {}] if endpoint
784
802
 
785
803
  variable(env) || globbed_or_mounted(env)
@@ -800,7 +818,7 @@ module Hanami
800
818
  end
801
819
 
802
820
  if as
803
- as = prefixed_name(as)
821
+ as = prefixed_underscored_name(as)
804
822
  add_named_route(path, as, constraints)
805
823
  end
806
824
 
@@ -872,10 +890,13 @@ module Hanami
872
890
  @path_prefix.join(path).to_s
873
891
  end
874
892
 
875
- # @since 2.0.0
893
+ # @since x.x.x
876
894
  # @api private
877
- def prefixed_name(name)
878
- @name_prefix.relative_join(name, PREFIXED_NAME_SEPARATOR).to_sym
895
+ def prefixed_underscored_name(name)
896
+ @name_prefix
897
+ .relative_join(name, PREFIXED_NAME_SEPARATOR)
898
+ .gsub(UNDERSCORED_NAME_REGEXP, "_")
899
+ .to_sym
879
900
  end
880
901
 
881
902
  # Returns a new instance of Hanami::Router with the modified options.
@@ -907,7 +928,13 @@ module Hanami
907
928
  raise UnknownHTTPStatusCodeError.new(code)
908
929
  end
909
930
 
910
- destination = prefixed_path(to)
931
+ destination = if to.is_a?(URI)
932
+ to.to_s
933
+ elsif to.start_with?("http://") || to.start_with?("https://")
934
+ to
935
+ else
936
+ prefixed_path(to)
937
+ end
911
938
  Redirect.new(destination, code, ->(*) { [code, {HTTP_HEADER_LOCATION => destination}, [body]] })
912
939
  end
913
940
 
@@ -925,6 +952,7 @@ module Hanami
925
952
  env[PARAMS].merge!(::Rack::Utils.parse_nested_query(env[::Rack::QUERY_STRING]))
926
953
  env[PARAMS].merge!(params)
927
954
  env[PARAMS] = Params.deep_symbolize(env[PARAMS])
955
+
928
956
  env
929
957
  end
930
958
 
metadata CHANGED
@@ -1,27 +1,26 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-router
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-11-05 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: rack
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - "~>"
16
+ - - ">="
18
17
  - !ruby/object:Gem::Version
19
18
  version: '2.0'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
- - - "~>"
23
+ - - ">="
25
24
  - !ruby/object:Gem::Version
26
25
  version: '2.0'
27
26
  - !ruby/object:Gem::Dependency
@@ -52,6 +51,20 @@ dependencies:
52
51
  - - "~>"
53
52
  - !ruby/object:Gem::Version
54
53
  version: '3.0'
54
+ - !ruby/object:Gem::Dependency
55
+ name: csv
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.3'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.3'
55
68
  - !ruby/object:Gem::Dependency
56
69
  name: bundler
57
70
  requirement: !ruby/object:Gem::Requirement
@@ -92,14 +105,14 @@ dependencies:
92
105
  requirements:
93
106
  - - "~>"
94
107
  - !ruby/object:Gem::Version
95
- version: '1.0'
108
+ version: '2.0'
96
109
  type: :development
97
110
  prerelease: false
98
111
  version_requirements: !ruby/object:Gem::Requirement
99
112
  requirements:
100
113
  - - "~>"
101
114
  - !ruby/object:Gem::Version
102
- version: '1.0'
115
+ version: '2.0'
103
116
  - !ruby/object:Gem::Dependency
104
117
  name: rspec
105
118
  requirement: !ruby/object:Gem::Requirement
@@ -176,6 +189,7 @@ files:
176
189
  - lib/hanami/router/node.rb
177
190
  - lib/hanami/router/params.rb
178
191
  - lib/hanami/router/prefix.rb
192
+ - lib/hanami/router/rack_utils.rb
179
193
  - lib/hanami/router/recognized_route.rb
180
194
  - lib/hanami/router/redirect.rb
181
195
  - lib/hanami/router/route.rb
@@ -188,7 +202,6 @@ licenses:
188
202
  - MIT
189
203
  metadata:
190
204
  rubygems_mfa_required: 'true'
191
- post_install_message:
192
205
  rdoc_options: []
193
206
  require_paths:
194
207
  - lib
@@ -203,8 +216,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
203
216
  - !ruby/object:Gem::Version
204
217
  version: '0'
205
218
  requirements: []
206
- rubygems_version: 3.5.22
207
- signing_key:
219
+ rubygems_version: 3.6.9
208
220
  specification_version: 4
209
221
  summary: Rack compatible HTTP router for Ruby and Hanami
210
222
  test_files: []