hanami-router 2.0.0.alpha1 → 2.0.0.alpha2

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.
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mustermann/rails"
4
+
5
+ module Hanami
6
+ class Router
7
+ # Route path
8
+ #
9
+ # @since 2.0.0
10
+ # @api private
11
+ class Segment
12
+ # @since 2.0.0
13
+ # @api private
14
+ def self.fabricate(segment, **constraints)
15
+ Mustermann.new(segment, type: :rails, version: "5.0", capture: constraints)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/router/node"
4
+
5
+ module Hanami
6
+ class Router
7
+ # Trie data structure to store routes
8
+ #
9
+ # @api private
10
+ # @since 2.0.0
11
+ class Trie
12
+ # @api private
13
+ # @since 2.0.0
14
+ attr_reader :root
15
+
16
+ # @api private
17
+ # @since 2.0.0
18
+ def initialize
19
+ @root = Node.new
20
+ end
21
+
22
+ # @api private
23
+ # @since 2.0.0
24
+ def add(path, to, constraints)
25
+ node = @root
26
+ for_each_segment(path) do |segment|
27
+ node = node.put(segment, constraints)
28
+ end
29
+
30
+ node.leaf!(to)
31
+ end
32
+
33
+ # @api private
34
+ # @since 2.0.0
35
+ def find(path)
36
+ node = @root
37
+ params = {}
38
+
39
+ for_each_segment(path) do |segment|
40
+ break unless node
41
+
42
+ child, captures = node.get(segment)
43
+ params.merge!(captures) if captures
44
+
45
+ node = child
46
+ end
47
+
48
+ return [node.to, params] if node&.leaf?
49
+
50
+ nil
51
+ end
52
+
53
+ private
54
+
55
+ # @api private
56
+ # @since 2.0.0
57
+ def for_each_segment(path, &blk)
58
+ _, *segments = path.split(/\//)
59
+ segments.each(&blk)
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/router/error"
4
+ require "mustermann/error"
5
+
6
+ module Hanami
7
+ class Router
8
+ # URL Helpers
9
+ class UrlHelpers
10
+ # @since 2.0.0
11
+ # @api private
12
+ def initialize(base_url)
13
+ @base_url = base_url
14
+ @named = {}
15
+ end
16
+
17
+ # @since 2.0.0
18
+ # @api private
19
+ def add(name, segment)
20
+ @named[name] = segment
21
+ end
22
+
23
+ # @since 2.0.0
24
+ # @api public
25
+ def path(name, variables = {})
26
+ @named.fetch(name.to_sym) do
27
+ raise InvalidRouteException.new(name)
28
+ end.expand(:append, variables)
29
+ rescue Mustermann::ExpandError => exception
30
+ raise InvalidRouteExpansionException.new(name, exception.message)
31
+ end
32
+
33
+ # @since 2.0.0
34
+ # @api public
35
+ def url(name, variables = {})
36
+ @base_url + path(name, variables)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -3,6 +3,7 @@
3
3
  module Hanami
4
4
  class Router
5
5
  # @since 0.1.0
6
- VERSION = "2.0.0.alpha1"
6
+ # @api public
7
+ VERSION = "2.0.0.alpha2"
7
8
  end
8
9
  end
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.alpha1
4
+ version: 2.0.0.alpha2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-30 00:00:00.000000000 Z
11
+ date: 2020-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -52,34 +52,6 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.0'
55
- - !ruby/object:Gem::Dependency
56
- name: hanami-utils
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: 2.0.alpha
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: 2.0.alpha
69
- - !ruby/object:Gem::Dependency
70
- name: dry-inflector
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '0.1'
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '0.1'
83
55
  - !ruby/object:Gem::Dependency
84
56
  name: bundler
85
57
  requirement: !ruby/object:Gem::Requirement
@@ -106,14 +78,14 @@ dependencies:
106
78
  requirements:
107
79
  - - "~>"
108
80
  - !ruby/object:Gem::Version
109
- version: '12'
81
+ version: '13'
110
82
  type: :development
111
83
  prerelease: false
112
84
  version_requirements: !ruby/object:Gem::Requirement
113
85
  requirements:
114
86
  - - "~>"
115
87
  - !ruby/object:Gem::Version
116
- version: '12'
88
+ version: '13'
117
89
  - !ruby/object:Gem::Dependency
118
90
  name: rack-test
119
91
  requirement: !ruby/object:Gem::Requirement
@@ -134,14 +106,14 @@ dependencies:
134
106
  requirements:
135
107
  - - "~>"
136
108
  - !ruby/object:Gem::Version
137
- version: '3.7'
109
+ version: '3.8'
138
110
  type: :development
139
111
  prerelease: false
140
112
  version_requirements: !ruby/object:Gem::Requirement
141
113
  requirements:
142
114
  - - "~>"
143
115
  - !ruby/object:Gem::Version
144
- version: '3.7'
116
+ version: '3.8'
145
117
  description: Rack compatible HTTP router for Ruby
146
118
  email:
147
119
  - me@lucaguidi.com
@@ -159,20 +131,17 @@ files:
159
131
  - lib/hanami/middleware/body_parser/json_parser.rb
160
132
  - lib/hanami/middleware/error.rb
161
133
  - lib/hanami/router.rb
134
+ - lib/hanami/router/block.rb
135
+ - lib/hanami/router/error.rb
136
+ - lib/hanami/router/node.rb
137
+ - lib/hanami/router/params.rb
138
+ - lib/hanami/router/prefix.rb
139
+ - lib/hanami/router/recognized_route.rb
140
+ - lib/hanami/router/redirect.rb
141
+ - lib/hanami/router/segment.rb
142
+ - lib/hanami/router/trie.rb
143
+ - lib/hanami/router/url_helpers.rb
162
144
  - lib/hanami/router/version.rb
163
- - lib/hanami/routing.rb
164
- - lib/hanami/routing/endpoint.rb
165
- - lib/hanami/routing/endpoint_resolver.rb
166
- - lib/hanami/routing/prefix.rb
167
- - lib/hanami/routing/recognized_route.rb
168
- - lib/hanami/routing/resource.rb
169
- - lib/hanami/routing/resource/action.rb
170
- - lib/hanami/routing/resource/nested.rb
171
- - lib/hanami/routing/resource/options.rb
172
- - lib/hanami/routing/resources.rb
173
- - lib/hanami/routing/resources/action.rb
174
- - lib/hanami/routing/routes_inspector.rb
175
- - lib/hanami/routing/scope.rb
176
145
  homepage: http://hanamirb.org
177
146
  licenses:
178
147
  - MIT
@@ -192,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
192
161
  - !ruby/object:Gem::Version
193
162
  version: 1.3.1
194
163
  requirements: []
195
- rubygems_version: 3.0.2
164
+ rubygems_version: 3.1.2
196
165
  signing_key:
197
166
  specification_version: 4
198
167
  summary: Rack compatible HTTP router for Ruby and Hanami
@@ -1,193 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "uri"
4
- require "rack/utils"
5
- require "mustermann/rails"
6
-
7
- # Hanami
8
- #
9
- # @since 0.1.0
10
- module Hanami
11
- # Hanami routing
12
- #
13
- # @since 0.1.0
14
- module Routing
15
- PATH_INFO = "PATH_INFO"
16
- QUERY_STRING = "QUERY_STRING"
17
- REQUEST_METHOD = "REQUEST_METHOD"
18
-
19
- HTTP_VERBS = %w[get post delete put patch trace options link unlink].freeze
20
-
21
- PARAMS = "router.params"
22
-
23
- def self.http_verbs
24
- HTTP_VERBS
25
- end
26
-
27
- # @since 0.5.0
28
- class Error < ::StandardError
29
- end
30
-
31
- # Invalid route
32
- # This is raised when the router fails to recognize a route, because of the
33
- # given arguments.
34
- #
35
- # @since 0.1.0
36
- class InvalidRouteException < Error
37
- end
38
-
39
- # Endpoint not found
40
- # This is raised when the router fails to load an endpoint at the runtime.
41
- #
42
- # @since 0.1.0
43
- class EndpointNotFound < Error
44
- end
45
-
46
- # @since 2.0.0
47
- class NotCallableEndpointError < Error
48
- def initialize(endpoint)
49
- super("#{endpoint.inspect} isn't compatible with Rack. Please make sure it implements #call.")
50
- end
51
- end
52
-
53
- # HTTP redirect
54
- #
55
- # @since 2.0.0
56
- # @api private
57
- class Redirect
58
- # @since 2.0.0
59
- # @api private
60
- LOCATION = "Location"
61
-
62
- # @since 2.0.0
63
- # @api private
64
- STATUS_RANGE = (300..399).freeze
65
-
66
- attr_reader :path
67
- alias destination_path path
68
-
69
- # Instantiate a new redirect
70
- #
71
- # @param path [String] a relative or absolute URI
72
- # @param status [Integer] a redirect status (an integer between `300` and `399`)
73
- #
74
- # @return [Hanami::Routing::Redirect] a new instance
75
- #
76
- # @raise [ArgumentError] if path is nil, or status code isn't a redirect
77
- #
78
- # @since 2.0.0
79
- # @api private
80
- def initialize(path, status)
81
- raise ArgumentError.new("Path is nil") if path.nil?
82
- raise ArgumentError.new("Status code isn't a redirect: #{status.inspect}") unless STATUS_RANGE.include?(status)
83
-
84
- @path = path
85
- @status = status
86
- freeze
87
- end
88
-
89
- def call(*)
90
- [@status, { LOCATION => @path }, []]
91
- end
92
-
93
- def redirect?
94
- true
95
- end
96
- end
97
-
98
- # Route
99
- #
100
- # @since 0.1.0
101
- # @api private
102
- class Route
103
- # @since 0.7.0
104
- # @api private
105
- def initialize(verb, path, endpoint, constraints)
106
- @verb = verb
107
- @path = Mustermann.new(path, type: :rails, version: "5.0", capture: constraints)
108
- @endpoint = endpoint
109
- freeze
110
- end
111
-
112
- # @since 0.1.0
113
- # @api private
114
- def call(env)
115
- env[PARAMS] ||= {}
116
- env[PARAMS].merge!(Rack::Utils.parse_nested_query(env[QUERY_STRING]))
117
- env[PARAMS].merge!(@path.params(env[PATH_INFO]))
118
- env[PARAMS] = Utils::Hash.deep_symbolize(env[PARAMS])
119
-
120
- @endpoint.call(env)
121
- end
122
-
123
- # @since 0.1.0
124
- # @api private
125
- def path(args)
126
- @path.expand(:append, args)
127
- rescue Mustermann::ExpandError => e
128
- raise Hanami::Routing::InvalidRouteException.new(e.message)
129
- end
130
-
131
- # @since 2.0.0
132
- # @api private
133
- def match?(env)
134
- match_path?(env) &&
135
- @verb.include?(env[REQUEST_METHOD])
136
- end
137
-
138
- # @since 2.0.0
139
- # @api private
140
- def match_path?(env)
141
- @path =~ env[PATH_INFO]
142
- end
143
- end
144
-
145
- # @since 2.0.0
146
- # @api private
147
- module Uri
148
- # @since 2.0.0
149
- # @api private
150
- HTTP = "http"
151
-
152
- # @since 2.0.0
153
- # @api private
154
- HTTPS = "https"
155
-
156
- # @since 2.0.0
157
- # @api private
158
- DEFAULT_SCHEME = HTTP
159
-
160
- # Build a URI string from the given arguments
161
- #
162
- # @param scheme [String] the URI scheme: one of `"http"` or `"https"`
163
- # @param host [String] the URI host
164
- # @param port [String,Integer] the URI port
165
- #
166
- # @raise [ArgumentError] if one of `scheme`, `host`, `port` is `nil`, or
167
- # if `scheme` is unknown
168
- #
169
- # @since 2.0.0
170
- # @api private
171
- def self.build(scheme:, host:, port:)
172
- raise ArgumentError.new("host is nil") if host.nil?
173
- raise ArgumentError.new("port is nil") if port.nil?
174
-
175
- case scheme
176
- when HTTP
177
- URI::HTTP
178
- when HTTPS
179
- URI::HTTPS
180
- else
181
- raise ArgumentError.new("Unknown scheme: #{scheme.inspect}")
182
- end.build(scheme: scheme, host: host, port: port).to_s
183
- end
184
- end
185
-
186
- require "hanami/routing/endpoint"
187
- require "hanami/routing/prefix"
188
- require "hanami/routing/scope"
189
- require "hanami/routing/resource"
190
- require "hanami/routing/resources"
191
- require "hanami/routing/recognized_route"
192
- end
193
- end