hanami-router 2.0.2 → 2.1.0.beta1

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: 8591e8a6f364610506f486230b6d68f371ddc256d8e4a8c799702298974a9614
4
- data.tar.gz: e3a7aef5d85e5dda768ea06f1c55c88d9c1fab0990e09dbe680911497734a76c
3
+ metadata.gz: 5a8c8c2f5afa3afa7c514d2f73a471bb8e0276173d830e796527ddfbb9dc2e9f
4
+ data.tar.gz: e4976449349a55717ec2d1e4adf8e63391a4c0899eb48e14303050a83ca58dcc
5
5
  SHA512:
6
- metadata.gz: b3b1ad34d5f2d4ccf94c5cf040353e6971152c92743212006a7001dc3294148e55b5d96ab73b2a727f173d464ba7129bd369daa4c6e393bc2b1b4b64dd4c5c97
7
- data.tar.gz: 6affe5765f2bbdff84c34ecbfa2d0b924d9e0d5f30394893f42febebcbd1744802b32b81c09ffbadc4fe30c3d8ab255eaa69b5995a18459b029973a4ffaed392
6
+ metadata.gz: 2022d72abcaad4a9aa4099e69356da269355a5d43b7ad878aeb613fbe4cb26b56f2611f27e4fd65f8bcb4543b5a65e28b4668f83acc35de07bd553c6c99ae341
7
+ data.tar.gz: 8bbf159f95fa83d3f1ca4a55e849398a6156ed0630d2dfe831bfb17b5b15f970a26cacbec83c242f3e9f4d1831d8869d1761a160a7724e1a2cec56a2e763d46d
data/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  Rack compatible HTTP router for Ruby
4
4
 
5
+ ## v2.1.0.beta1 - 2023-06-29
6
+
7
+ ### Added
8
+
9
+ - [Tim Riley] Accept `not_allowed_proc:` argument when initializing `Hanami::Router`. This allows
10
+ customisation of the `not_allowed` behavior like for `not_found` (#259)
11
+
5
12
  ## v2.0.2 - 2022-12-25
6
13
 
7
14
  ### Added
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright © 2014-2021 Luca Guidi
1
+ Copyright © 2014 Hanami Team
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -365,4 +365,4 @@ __Hanami::Router__ uses [Semantic Versioning 2.0.0](http://semver.org)
365
365
 
366
366
  ## Copyright
367
367
 
368
- Copyright © 2014-2022 Hanami Team – Released under MIT License
368
+ Copyright © 2014 Hanami Team – Released under MIT License
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rack/builder"
4
- require_relative "./trie"
4
+ require_relative "trie"
5
5
 
6
6
  module Hanami
7
7
  module Middleware
@@ -115,7 +115,7 @@ module Hanami
115
115
  # @api private
116
116
  # @since 1.3.0
117
117
  def classify(parser)
118
- parser.to_s.split(/_/).map(&:capitalize).join
118
+ parser.to_s.split("_").map(&:capitalize).join
119
119
  end
120
120
 
121
121
  # @api private
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "hanami/router/segment"
4
+
3
5
  module Hanami
4
6
  module Middleware
5
7
  # Trie node to register scopes with custom Rack middleware
@@ -15,26 +17,46 @@ module Hanami
15
17
  # @since 2.0.0
16
18
  def initialize
17
19
  @app = nil
18
- @children = {}
20
+ @variable = nil
21
+ @fixed = nil
19
22
  end
20
23
 
21
24
  # @api private
22
25
  # @since 2.0.0
23
26
  def freeze
24
- @children.freeze
27
+ @variable.freeze
28
+ @fixed.freeze
25
29
  super
26
30
  end
27
31
 
28
32
  # @api private
29
33
  # @since 2.0.0
30
34
  def put(segment)
31
- @children[segment] ||= self.class.new
35
+ if variable?(segment)
36
+ @variable ||= {}
37
+ @variable[segment_for(segment)] ||= self.class.new
38
+ else
39
+ @fixed ||= {}
40
+ @fixed[segment] ||= self.class.new
41
+ end
32
42
  end
33
43
 
34
44
  # @api private
35
45
  # @since 2.0.0
36
- def get(segment)
37
- @children.fetch(segment) { self if leaf? }
46
+ def get(segment) # rubocop:disable Metrics/PerceivedComplexity
47
+ found = @fixed&.fetch(segment, nil)
48
+ return found if found
49
+
50
+ @variable&.each do |matcher, node|
51
+ break if found
52
+
53
+ captured = matcher.match(segment)
54
+ found = node if captured
55
+ end
56
+
57
+ return found if found
58
+
59
+ self if leaf?
38
60
  end
39
61
 
40
62
  # @api private
@@ -52,7 +74,19 @@ module Hanami
52
74
  # @api private
53
75
  # @since 2.0.0
54
76
  def leaf?
55
- @children.empty?
77
+ @fixed.nil? && @variable.nil?
78
+ end
79
+
80
+ # @api private
81
+ # @since 2.0.3
82
+ def variable?(segment)
83
+ Router::ROUTE_VARIABLE_MATCHER.match?(segment)
84
+ end
85
+
86
+ # @api private
87
+ # @since 2.0.3
88
+ def segment_for(segment)
89
+ Router::Segment.fabricate(segment)
56
90
  end
57
91
  end
58
92
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "./node"
3
+ require_relative "node"
4
4
 
5
5
  module Hanami
6
6
  module Middleware
@@ -61,7 +61,7 @@ module Hanami
61
61
  # @api private
62
62
  # @since 2.0.0
63
63
  def for_each_segment(path, &blk)
64
- _, *segments = path.split(/\//)
64
+ _, *segments = path.split("/")
65
65
  segments.each(&blk)
66
66
  end
67
67
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "hanami/router/errors"
4
4
  require "mustermann/error"
5
+ require_relative "prefix"
5
6
 
6
7
  module Hanami
7
8
  class Router
@@ -11,8 +12,11 @@ module Hanami
11
12
  # @since 2.0.0
12
13
  # @api private
13
14
  def initialize(base_url)
14
- @base_url = base_url
15
+ @base_url = URI(base_url)
15
16
  @named = {}
17
+ prefix = @base_url.path
18
+ prefix = DEFAULT_PREFIX if prefix.empty?
19
+ @prefix = Prefix.new(prefix)
16
20
  end
17
21
 
18
22
  # @since 2.0.0
@@ -34,7 +38,7 @@ module Hanami
34
38
  # @since 2.0.0
35
39
  # @api private
36
40
  def url(name, variables = {})
37
- @base_url + path(name, variables)
41
+ @base_url + @prefix.join(path(name, variables)).to_s
38
42
  end
39
43
  end
40
44
  end
@@ -8,6 +8,6 @@ module Hanami
8
8
  #
9
9
  # @since 0.1.0
10
10
  # @api public
11
- VERSION = "2.0.2"
11
+ VERSION = "2.1.0.beta1"
12
12
  end
13
13
  end
data/lib/hanami/router.rb CHANGED
@@ -72,13 +72,14 @@ module Hanami
72
72
  # Hanami::Router.new do
73
73
  # get "/", to: ->(*) { [200, {}, ["OK"]] }
74
74
  # end
75
- def initialize(base_url: DEFAULT_BASE_URL, prefix: DEFAULT_PREFIX, resolver: DEFAULT_RESOLVER, not_found: NOT_FOUND, block_context: nil, inspector: nil, &blk) # rubocop:disable Layout/LineLength
75
+ def initialize(base_url: DEFAULT_BASE_URL, prefix: DEFAULT_PREFIX, resolver: DEFAULT_RESOLVER, not_allowed: NOT_ALLOWED, not_found: NOT_FOUND, block_context: nil, inspector: nil, &blk) # rubocop:disable Layout/LineLength
76
76
  # TODO: verify if Prefix can handle both name and path prefix
77
77
  @path_prefix = Prefix.new(prefix)
78
78
  @name_prefix = Prefix.new("")
79
79
  @url_helpers = UrlHelpers.new(base_url)
80
80
  @base_url = base_url
81
81
  @resolver = resolver
82
+ @not_allowed = not_allowed
82
83
  @not_found = not_found
83
84
  @block_context = block_context
84
85
  @fixed = {}
@@ -101,8 +102,7 @@ module Hanami
101
102
  endpoint, params = lookup(env)
102
103
 
103
104
  unless endpoint
104
- return not_allowed(env) ||
105
- not_found(env)
105
+ return not_allowed(env) || not_found(env)
106
106
  end
107
107
 
108
108
  endpoint.call(
@@ -147,7 +147,7 @@ module Hanami
147
147
  # end
148
148
  #
149
149
  # router.path(:root) # => "/"
150
- # router.url(:root) # => "https://hanamirb.org"
150
+ # router.url(:root) # => #<URI::HTTPS https://hanamirb.org>
151
151
  def root(to: nil, &blk)
152
152
  get(ROOT_PATH, to: to, as: :root, &blk)
153
153
  end
@@ -191,7 +191,7 @@ module Hanami
191
191
  # end
192
192
  #
193
193
  # router.path(:welcome) # => "/"
194
- # router.url(:welcome) # => "http://localhost/"
194
+ # router.url(:welcome) # => #<URI::HTTP http://localhost/>
195
195
  #
196
196
  # @example Constraints
197
197
  # require "hanami/router"
@@ -466,7 +466,7 @@ module Hanami
466
466
  #
467
467
  # @param name [Symbol] the route name
468
468
  #
469
- # @return [String]
469
+ # @return [URI::HTTP, URI::HTTPS]
470
470
  #
471
471
  # @raise [Hanami::Router::MissingRouteError] when the router fails to
472
472
  # recognize a route, because of the given arguments.
@@ -483,9 +483,9 @@ module Hanami
483
483
  # get "/:name", to: ->(*) { ... }, as: :framework
484
484
  # end
485
485
  #
486
- # router.url(:login) # => "https://hanamirb.org/login"
487
- # router.url(:login, return_to: "/dashboard") # => "https://hanamirb.org/login?return_to=%2Fdashboard"
488
- # router.url(:framework, name: "router") # => "https://hanamirb.org/router"
486
+ # router.url(:login) # => #<URI::HTTPS https://hanamirb.org/login>
487
+ # router.url(:login, return_to: "/dashboard") # => #<URI::HTTPS https://hanamirb.org/login?return_to=%2Fdashboard>
488
+ # router.url(:framework, name: "router") # => #<URI::HTTPS https://hanamirb.org/router>
489
489
  def url(name, variables = {})
490
490
  url_helpers.url(name, variables)
491
491
  end
@@ -652,15 +652,10 @@ module Hanami
652
652
  # @since 2.0.0
653
653
  # @api private
654
654
  def not_allowed(env)
655
- http_methods = _not_allowed_fixed(env) || _not_allowed_variable(env)
656
- return if http_methods.nil?
655
+ allowed_http_methods = _not_allowed_fixed(env) || _not_allowed_variable(env)
656
+ return if allowed_http_methods.nil?
657
657
 
658
- [HTTP_STATUS_NOT_ALLOWED,
659
- {
660
- ::Rack::CONTENT_LENGTH => HTTP_BODY_NOT_ALLOWED_LENGTH,
661
- "Allow" => http_methods.join(", ")
662
- },
663
- [HTTP_BODY_NOT_ALLOWED]]
658
+ @not_allowed.call(env, allowed_http_methods)
664
659
  end
665
660
 
666
661
  # @since 2.0.0
@@ -776,6 +771,21 @@ module Hanami
776
771
  # @api private
777
772
  ROUTE_GLOBBED_MATCHER = /\*/
778
773
 
774
+ # Default response when the route method was not allowed
775
+ #
776
+ # @api private
777
+ # @since 2.1.0
778
+ NOT_ALLOWED = -> (_, allowed_http_methods) {
779
+ [
780
+ HTTP_STATUS_NOT_ALLOWED,
781
+ {
782
+ ::Rack::CONTENT_LENGTH => HTTP_BODY_NOT_ALLOWED_LENGTH,
783
+ "Allow" => allowed_http_methods.join(", ")
784
+ },
785
+ [HTTP_BODY_NOT_ALLOWED]
786
+ ]
787
+ }
788
+
779
789
  # Default response when no route was matched
780
790
  #
781
791
  # @api private
@@ -790,7 +800,7 @@ module Hanami
790
800
  endpoint = fixed(env)
791
801
  return [endpoint, {}] if endpoint
792
802
 
793
- variable(env) || globbed(env) || mounted(env)
803
+ variable(env) || mounted(env) || globbed(env)
794
804
  end
795
805
 
796
806
  # @since 2.0.0
@@ -900,6 +910,7 @@ module Hanami
900
910
  base_url: @base_url,
901
911
  prefix: @path_prefix.to_s,
902
912
  resolver: @resolver,
913
+ not_allowed: @not_allowed,
903
914
  not_found: @not_found,
904
915
  block_context: @block_context,
905
916
  inspector: @inspector
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.2
4
+ version: 2.1.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-25 00:00:00.000000000 Z
11
+ date: 2023-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -196,11 +196,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
196
196
  version: '3.0'
197
197
  required_rubygems_version: !ruby/object:Gem::Requirement
198
198
  requirements:
199
- - - ">="
199
+ - - ">"
200
200
  - !ruby/object:Gem::Version
201
- version: '0'
201
+ version: 1.3.1
202
202
  requirements: []
203
- rubygems_version: 3.4.1
203
+ rubygems_version: 3.4.13
204
204
  signing_key:
205
205
  specification_version: 4
206
206
  summary: Rack compatible HTTP router for Ruby and Hanami