hanami-router 1.3.1 → 2.0.0.alpha4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -0
  3. data/LICENSE.md +1 -1
  4. data/README.md +97 -443
  5. data/hanami-router.gemspec +23 -19
  6. data/lib/hanami/middleware/body_parser.rb +21 -15
  7. data/lib/hanami/middleware/body_parser/class_interface.rb +62 -56
  8. data/lib/hanami/middleware/body_parser/errors.rb +7 -4
  9. data/lib/hanami/middleware/body_parser/json_parser.rb +9 -7
  10. data/lib/hanami/middleware/body_parser/parser.rb +58 -0
  11. data/lib/hanami/middleware/error.rb +16 -0
  12. data/lib/hanami/router.rb +548 -957
  13. data/lib/hanami/router/block.rb +88 -0
  14. data/lib/hanami/router/error.rb +67 -0
  15. data/lib/hanami/router/node.rb +91 -0
  16. data/lib/hanami/router/params.rb +35 -0
  17. data/lib/hanami/router/prefix.rb +67 -0
  18. data/lib/hanami/router/recognized_route.rb +92 -0
  19. data/lib/hanami/router/redirect.rb +28 -0
  20. data/lib/hanami/router/segment.rb +19 -0
  21. data/lib/hanami/router/trie.rb +63 -0
  22. data/lib/hanami/router/url_helpers.rb +40 -0
  23. data/lib/hanami/router/version.rb +4 -1
  24. metadata +61 -41
  25. data/lib/hanami-router.rb +0 -1
  26. data/lib/hanami/routing/endpoint.rb +0 -195
  27. data/lib/hanami/routing/endpoint_resolver.rb +0 -238
  28. data/lib/hanami/routing/error.rb +0 -7
  29. data/lib/hanami/routing/force_ssl.rb +0 -212
  30. data/lib/hanami/routing/http_router.rb +0 -220
  31. data/lib/hanami/routing/http_router_monkey_patch.rb +0 -38
  32. data/lib/hanami/routing/namespace.rb +0 -98
  33. data/lib/hanami/routing/parsers.rb +0 -113
  34. data/lib/hanami/routing/parsing/json_parser.rb +0 -33
  35. data/lib/hanami/routing/parsing/parser.rb +0 -61
  36. data/lib/hanami/routing/recognized_route.rb +0 -219
  37. data/lib/hanami/routing/resource.rb +0 -119
  38. data/lib/hanami/routing/resource/action.rb +0 -402
  39. data/lib/hanami/routing/resource/nested.rb +0 -41
  40. data/lib/hanami/routing/resource/options.rb +0 -74
  41. data/lib/hanami/routing/resources.rb +0 -48
  42. data/lib/hanami/routing/resources/action.rb +0 -156
  43. data/lib/hanami/routing/route.rb +0 -71
  44. data/lib/hanami/routing/routes_inspector.rb +0 -221
@@ -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
@@ -1,6 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Hanami
2
4
  class Router
3
5
  # @since 0.1.0
4
- VERSION = '1.3.1'.freeze
6
+ # @api public
7
+ VERSION = "2.0.0.alpha4"
5
8
  end
6
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: 1.3.1
4
+ version: 2.0.0.alpha4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-18 00:00:00.000000000 Z
11
+ date: 2021-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -25,33 +25,33 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: http_router
28
+ name: mustermann
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '='
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.11.2
33
+ version: '1.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '='
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.11.2
40
+ version: '1.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: hanami-utils
42
+ name: mustermann-contrib
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.3'
47
+ version: '1.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.3'
54
+ version: '1.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -78,14 +78,14 @@ dependencies:
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: '12'
81
+ version: '13'
82
82
  type: :development
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: '12'
88
+ version: '13'
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: rack-test
91
91
  requirement: !ruby/object:Gem::Requirement
@@ -106,14 +106,42 @@ dependencies:
106
106
  requirements:
107
107
  - - "~>"
108
108
  - !ruby/object:Gem::Version
109
- version: '3.7'
109
+ version: '3.8'
110
110
  type: :development
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - "~>"
115
115
  - !ruby/object:Gem::Version
116
- version: '3.7'
116
+ version: '3.8'
117
+ - !ruby/object:Gem::Dependency
118
+ name: rubocop
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - '='
122
+ - !ruby/object:Gem::Version
123
+ version: '0.91'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - '='
129
+ - !ruby/object:Gem::Version
130
+ version: '0.91'
131
+ - !ruby/object:Gem::Dependency
132
+ name: rubocop-performance
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - '='
136
+ - !ruby/object:Gem::Version
137
+ version: 1.8.1
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - '='
143
+ - !ruby/object:Gem::Version
144
+ version: 1.8.1
117
145
  description: Rack compatible HTTP router for Ruby
118
146
  email:
119
147
  - me@lucaguidi.com
@@ -125,37 +153,29 @@ files:
125
153
  - LICENSE.md
126
154
  - README.md
127
155
  - hanami-router.gemspec
128
- - lib/hanami-router.rb
129
156
  - lib/hanami/middleware/body_parser.rb
130
157
  - lib/hanami/middleware/body_parser/class_interface.rb
131
158
  - lib/hanami/middleware/body_parser/errors.rb
132
159
  - lib/hanami/middleware/body_parser/json_parser.rb
160
+ - lib/hanami/middleware/body_parser/parser.rb
161
+ - lib/hanami/middleware/error.rb
133
162
  - lib/hanami/router.rb
163
+ - lib/hanami/router/block.rb
164
+ - lib/hanami/router/error.rb
165
+ - lib/hanami/router/node.rb
166
+ - lib/hanami/router/params.rb
167
+ - lib/hanami/router/prefix.rb
168
+ - lib/hanami/router/recognized_route.rb
169
+ - lib/hanami/router/redirect.rb
170
+ - lib/hanami/router/segment.rb
171
+ - lib/hanami/router/trie.rb
172
+ - lib/hanami/router/url_helpers.rb
134
173
  - lib/hanami/router/version.rb
135
- - lib/hanami/routing/endpoint.rb
136
- - lib/hanami/routing/endpoint_resolver.rb
137
- - lib/hanami/routing/error.rb
138
- - lib/hanami/routing/force_ssl.rb
139
- - lib/hanami/routing/http_router.rb
140
- - lib/hanami/routing/http_router_monkey_patch.rb
141
- - lib/hanami/routing/namespace.rb
142
- - lib/hanami/routing/parsers.rb
143
- - lib/hanami/routing/parsing/json_parser.rb
144
- - lib/hanami/routing/parsing/parser.rb
145
- - lib/hanami/routing/recognized_route.rb
146
- - lib/hanami/routing/resource.rb
147
- - lib/hanami/routing/resource/action.rb
148
- - lib/hanami/routing/resource/nested.rb
149
- - lib/hanami/routing/resource/options.rb
150
- - lib/hanami/routing/resources.rb
151
- - lib/hanami/routing/resources/action.rb
152
- - lib/hanami/routing/route.rb
153
- - lib/hanami/routing/routes_inspector.rb
154
174
  homepage: http://hanamirb.org
155
175
  licenses:
156
176
  - MIT
157
177
  metadata: {}
158
- post_install_message:
178
+ post_install_message:
159
179
  rdoc_options: []
160
180
  require_paths:
161
181
  - lib
@@ -163,15 +183,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
163
183
  requirements:
164
184
  - - ">="
165
185
  - !ruby/object:Gem::Version
166
- version: 2.3.0
186
+ version: 2.6.0
167
187
  required_rubygems_version: !ruby/object:Gem::Requirement
168
188
  requirements:
169
- - - ">="
189
+ - - ">"
170
190
  - !ruby/object:Gem::Version
171
- version: '0'
191
+ version: 1.3.1
172
192
  requirements: []
173
- rubygems_version: 3.0.2
174
- signing_key:
193
+ rubygems_version: 3.2.4
194
+ signing_key:
175
195
  specification_version: 4
176
196
  summary: Rack compatible HTTP router for Ruby and Hanami
177
197
  test_files: []
@@ -1 +0,0 @@
1
- require 'hanami/router'
@@ -1,195 +0,0 @@
1
- require 'delegate'
2
- require 'hanami/routing/error'
3
- require 'hanami/utils/class'
4
-
5
- module Hanami
6
- module Routing
7
- # Endpoint not found
8
- # This is raised when the router fails to load an endpoint at the runtime.
9
- #
10
- # @since 0.1.0
11
- class EndpointNotFound < Hanami::Routing::Error
12
- end
13
-
14
- # Routing endpoint
15
- # This is the object that responds to an HTTP request made against a certain
16
- # path.
17
- #
18
- # The router will use this class for:
19
- #
20
- # * Procs and any Rack compatible object (respond to #call)
21
- #
22
- # @since 0.1.0
23
- #
24
- # @api private
25
- #
26
- # @example
27
- # require 'hanami/router'
28
- #
29
- # Hanami::Router.new do
30
- # get '/proc', to: ->(env) { [200, {}, ['This will use Hanami::Routing::Endpoint']] }
31
- # get '/rack-app', to: RackApp.new
32
- # end
33
- class Endpoint < SimpleDelegator
34
- # @since 0.2.0
35
- # @api private
36
- def inspect
37
- case __getobj__
38
- when Proc
39
- source, line = __getobj__.source_location
40
- lambda_inspector = " (lambda)" if __getobj__.lambda?
41
-
42
- "#<Proc@#{ ::File.expand_path(source) }:#{ line }#{ lambda_inspector }>"
43
- when Class
44
- __getobj__
45
- else
46
- "#<#{ __getobj__.class }>"
47
- end
48
- end
49
-
50
- # @since 1.0.0
51
- # @api private
52
- def routable?
53
- !__getobj__.nil?
54
- rescue ArgumentError
55
- end
56
-
57
- # @since 1.0.1
58
- # @api private
59
- def redirect?
60
- false
61
- end
62
-
63
- # @since 1.0.1
64
- # @api private
65
- def destination_path
66
- end
67
- end
68
-
69
- # Routing endpoint
70
- # This is the object that responds to an HTTP request made against a certain
71
- # path.
72
- #
73
- # The router will use this class for:
74
- #
75
- # * Classes
76
- # * Hanami::Action endpoints referenced as a class
77
- # * Hanami::Action endpoints referenced a string
78
- # * RESTful resource(s)
79
- #
80
- # @since 0.1.0
81
- #
82
- # @api private
83
- #
84
- # @example
85
- # require 'hanami/router'
86
- #
87
- # Hanami::Router.new do
88
- # get '/class', to: RackMiddleware
89
- # get '/hanami-action-class', to: Dashboard::Index
90
- # get '/hanami-action-string', to: 'dashboard#index'
91
- #
92
- # resource 'identity'
93
- # resources 'articles'
94
- # end
95
- class ClassEndpoint < Endpoint
96
- # Rack interface
97
- #
98
- # @since 0.1.0
99
- # @api private
100
- def call(env)
101
- __getobj__.new.call(env)
102
- end
103
- end
104
-
105
- # Routing endpoint
106
- # This is the object that responds to an HTTP request made against a certain
107
- # path.
108
- #
109
- # The router will use this class for the same use cases of `ClassEndpoint`,
110
- # but when the target class can't be found, instead of raise a `LoadError`
111
- # we reference in a lazy endpoint.
112
- #
113
- # For each incoming HTTP request, it will look for the referenced class,
114
- # then it will instantiate and invoke #call on the object.
115
- #
116
- # This behavior is required to solve a chicken-egg situation when we try
117
- # to load the router first and then the application with all its endpoints.
118
- #
119
- # @since 0.1.0
120
- #
121
- # @api private
122
- #
123
- # @see Hanami::Routing::ClassEndpoint
124
- class LazyEndpoint < Endpoint
125
- # Initialize the lazy endpoint
126
- #
127
- # @since 0.1.0
128
- # @api private
129
- def initialize(name, namespace)
130
- @name, @namespace = name, namespace
131
- end
132
-
133
- # Rack interface
134
- #
135
- # @raise [EndpointNotFound] when the endpoint can't be found.
136
- #
137
- # @since 0.1.0
138
- # @api private
139
- def call(env)
140
- obj.call(env)
141
- end
142
-
143
- # @since 0.2.0
144
- # @api private
145
- def inspect
146
- # TODO review this implementation once the namespace feature will be
147
- # cleaned up.
148
- result = klass rescue nil
149
-
150
- if result.nil?
151
- result = @name
152
- result = "#{ @namespace }::#{ result }" if @namespace != Object
153
- end
154
-
155
- result
156
- end
157
-
158
- private
159
- # @since 0.1.0
160
- # @api private
161
- def obj
162
- klass.new
163
- end
164
-
165
- # @since 0.2.0
166
- # @api private
167
- def klass
168
- Utils::Class.load!(@name, @namespace)
169
- rescue NameError => e
170
- raise EndpointNotFound.new(e.message)
171
- end
172
- end
173
-
174
- # @since 1.0.1
175
- # @api private
176
- class RedirectEndpoint < Endpoint
177
- # @since 1.0.1
178
- # @api private
179
- attr_reader :destination_path
180
-
181
- # @since 1.0.1
182
- # @api private
183
- def initialize(destination_path, destination)
184
- @destination_path = destination_path
185
- super(destination)
186
- end
187
-
188
- # @since 1.0.1
189
- # @api private
190
- def redirect?
191
- true
192
- end
193
- end
194
- end
195
- end