hanami-router 1.3.2 → 2.0.0.alpha1

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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -3
  3. data/README.md +192 -154
  4. data/hanami-router.gemspec +23 -20
  5. data/lib/hanami/middleware/body_parser.rb +17 -13
  6. data/lib/hanami/middleware/body_parser/class_interface.rb +56 -56
  7. data/lib/hanami/middleware/body_parser/errors.rb +7 -4
  8. data/lib/hanami/middleware/body_parser/json_parser.rb +5 -3
  9. data/lib/hanami/middleware/error.rb +16 -0
  10. data/lib/hanami/router.rb +262 -149
  11. data/lib/hanami/router/version.rb +3 -1
  12. data/lib/hanami/routing.rb +193 -0
  13. data/lib/hanami/routing/endpoint.rb +122 -104
  14. data/lib/hanami/routing/endpoint_resolver.rb +20 -16
  15. data/lib/hanami/routing/prefix.rb +102 -0
  16. data/lib/hanami/routing/recognized_route.rb +40 -26
  17. data/lib/hanami/routing/resource.rb +9 -7
  18. data/lib/hanami/routing/resource/action.rb +58 -33
  19. data/lib/hanami/routing/resource/nested.rb +4 -1
  20. data/lib/hanami/routing/resource/options.rb +3 -1
  21. data/lib/hanami/routing/resources.rb +6 -4
  22. data/lib/hanami/routing/resources/action.rb +11 -6
  23. data/lib/hanami/routing/routes_inspector.rb +22 -20
  24. data/lib/hanami/routing/scope.rb +112 -0
  25. metadata +47 -25
  26. data/lib/hanami-router.rb +0 -1
  27. data/lib/hanami/routing/error.rb +0 -7
  28. data/lib/hanami/routing/force_ssl.rb +0 -212
  29. data/lib/hanami/routing/http_router.rb +0 -220
  30. data/lib/hanami/routing/http_router_monkey_patch.rb +0 -38
  31. data/lib/hanami/routing/namespace.rb +0 -98
  32. data/lib/hanami/routing/parsers.rb +0 -113
  33. data/lib/hanami/routing/parsing/json_parser.rb +0 -33
  34. data/lib/hanami/routing/parsing/parser.rb +0 -61
  35. data/lib/hanami/routing/route.rb +0 -71
@@ -1,98 +0,0 @@
1
- require 'delegate'
2
- require 'hanami/utils/path_prefix'
3
-
4
- module Hanami
5
- module Routing
6
- # Namespace for routes.
7
- # Implementation of Hanami::Router#namespace
8
- #
9
- # @since 0.1.0
10
- #
11
- # @api private
12
- #
13
- # @see Hanami::Router#namespace
14
- class Namespace < SimpleDelegator
15
- # @api private
16
- # @since 0.1.0
17
- def initialize(router, name, &blk)
18
- @router = router
19
- @name = Utils::PathPrefix.new(name)
20
- __setobj__(@router)
21
- instance_eval(&blk)
22
- end
23
-
24
- # @api private
25
- # @since 0.1.0
26
- def get(path, options = {}, &endpoint)
27
- super(@name.join(path), options, &endpoint)
28
- end
29
-
30
- # @api private
31
- # @since 0.1.0
32
- def post(path, options = {}, &endpoint)
33
- super(@name.join(path), options, &endpoint)
34
- end
35
-
36
- # @api private
37
- # @since 0.1.0
38
- def put(path, options = {}, &endpoint)
39
- super(@name.join(path), options, &endpoint)
40
- end
41
-
42
- # @api private
43
- # @since 0.1.0
44
- def patch(path, options = {}, &endpoint)
45
- super(@name.join(path), options, &endpoint)
46
- end
47
-
48
- # @api private
49
- # @since 0.1.0
50
- def delete(path, options = {}, &endpoint)
51
- super(@name.join(path), options, &endpoint)
52
- end
53
-
54
- # @api private
55
- # @since 0.1.0
56
- def trace(path, options = {}, &endpoint)
57
- super(@name.join(path), options, &endpoint)
58
- end
59
-
60
- # @api private
61
- # @since 0.1.0
62
- def options(path, options = {}, &endpoint)
63
- super(@name.join(path), options, &endpoint)
64
- end
65
-
66
- # @api private
67
- # @since 0.1.0
68
- def resource(name, options = {})
69
- super name, options.merge(namespace: @name.relative_join(options[:namespace]))
70
- end
71
-
72
- # @api private
73
- # @since 0.1.0
74
- def resources(name, options = {})
75
- super name, options.merge(namespace: @name.relative_join(options[:namespace]))
76
- end
77
-
78
- # @api private
79
- # @since 0.1.0
80
- def redirect(path, options = {}, &endpoint)
81
- super(@name.join(path), options.merge(to: @name.join(options[:to])), &endpoint)
82
- end
83
-
84
- # @api private
85
- # @since 1.1.0
86
- def mount(app, options)
87
- super(app, options.merge(at: @name.join(options[:at])))
88
- end
89
-
90
- # Supports nested namespaces
91
- # @api private
92
- # @since 0.1.0
93
- def namespace(name, &blk)
94
- Routing::Namespace.new(self, name, &blk)
95
- end
96
- end
97
- end
98
- end
@@ -1,113 +0,0 @@
1
- require 'hanami/routing/parsing/parser'
2
- require 'hanami/utils/hash'
3
-
4
- module Hanami
5
- module Routing
6
- # @since 0.2.0
7
- # @api private
8
- class Parsers
9
- # @since 0.2.0
10
- # @api private
11
- CONTENT_TYPE = 'CONTENT_TYPE'.freeze
12
-
13
- # @since 0.2.0
14
- # @api private
15
- MEDIA_TYPE_MATCHER = /\s*[;,]\s*/.freeze
16
-
17
- # @since 0.2.0
18
- # @api private
19
- RACK_INPUT = 'rack.input'.freeze
20
-
21
- # @since 0.2.0
22
- # @api private
23
- ROUTER_PARAMS = 'router.params'.freeze
24
-
25
- # @api private
26
- ROUTER_PARSED_BODY = 'router.parsed_body'.freeze
27
-
28
- # @api private
29
- FALLBACK_KEY = '_'.freeze
30
-
31
- # @since 0.2.0
32
- # @api private
33
- def initialize(parsers)
34
- @parsers = prepare(parsers)
35
- _redefine_call
36
- end
37
-
38
- # @since 0.2.0
39
- # @api private
40
- def call(env)
41
- env
42
- end
43
-
44
- private
45
- # @since 0.2.0
46
- # @api private
47
- def prepare(args)
48
- result = Hash.new
49
- args = Array(args)
50
- return result if args.empty?
51
-
52
- args.each do |arg|
53
- parser = Parsing::Parser.for(arg)
54
-
55
- parser.mime_types.each do |mime|
56
- result[mime] = parser
57
- end
58
- end
59
-
60
- result.default = Parsing::Parser.new
61
- result
62
- end
63
-
64
- # @since 0.2.0
65
- # @api private
66
- def _redefine_call
67
- return if @parsers.empty?
68
-
69
- define_singleton_method :call do |env|
70
- body = env[RACK_INPUT].read
71
- return env if body.empty?
72
-
73
- env[RACK_INPUT].rewind # somebody might try to read this stream
74
-
75
- env[ROUTER_PARAMS] ||= {} # prepare params
76
- env[ROUTER_PARSED_BODY] = _parse(env, body)
77
- env[ROUTER_PARAMS] = _symbolize(env[ROUTER_PARSED_BODY]).merge(env[ROUTER_PARAMS])
78
-
79
- env
80
- end
81
- end
82
-
83
- # @api private
84
- def _symbolize(body)
85
- if body.is_a?(Hash)
86
- Utils::Hash.deep_symbolize(body)
87
- else
88
- { FALLBACK_KEY => body }
89
- end
90
- end
91
-
92
- # @api private
93
- def _parse(env, body)
94
- @parsers[
95
- media_type(env)
96
- ].parse(body)
97
- end
98
-
99
- # @api private
100
- def media_type(env)
101
- if ct = content_type(env)
102
- ct.split(MEDIA_TYPE_MATCHER, 2).first.downcase
103
- end
104
- end
105
-
106
- # @api private
107
- def content_type(env)
108
- content_type = env[CONTENT_TYPE]
109
- content_type.nil? || content_type.empty? ? nil : content_type
110
- end
111
- end
112
- end
113
- end
@@ -1,33 +0,0 @@
1
- require 'hanami/utils/json'
2
-
3
- module Hanami
4
- module Routing
5
- module Parsing
6
- # @since 0.2.0
7
- # @api private
8
- class JsonParser < Parser
9
- # @since 0.2.0
10
- # @api private
11
- def mime_types
12
- ['application/json', 'application/vnd.api+json']
13
- end
14
-
15
- # Parse a json string
16
- #
17
- # @param body [String] a json string
18
- #
19
- # @return [Hash] the parsed json
20
- #
21
- # @raise [Hanami::Routing::Parsing::BodyParsingError] when the body can't be parsed.
22
- #
23
- # @since 0.2.0
24
- # @api private
25
- def parse(body)
26
- Hanami::Utils::Json.parse(body)
27
- rescue Hanami::Utils::Json::ParserError => e
28
- raise BodyParsingError.new(e.message)
29
- end
30
- end
31
- end
32
- end
33
- end
@@ -1,61 +0,0 @@
1
- require 'hanami/utils/class'
2
- require 'hanami/utils/string'
3
- require 'hanami/routing/error'
4
-
5
- module Hanami
6
- module Routing
7
- module Parsing
8
- # Body parsing error
9
- # This is raised when parser fails to parse the body
10
- #
11
- # @since 0.5.0
12
- class BodyParsingError < Hanami::Routing::Error
13
- end
14
-
15
- # @since 0.2.0
16
- class UnknownParserError < Hanami::Routing::Error
17
- # @since 0.2.0
18
- # @api private
19
- def initialize(parser)
20
- super("Unknown Parser: `#{ parser }'")
21
- end
22
- end
23
-
24
- # @since 0.2.0
25
- class Parser
26
- # @since 0.2.0
27
- # @api private
28
- def self.for(parser)
29
- case parser
30
- when String, Symbol
31
- require_parser(parser)
32
- else
33
- parser
34
- end
35
- end
36
-
37
- # @since 0.2.0
38
- def mime_types
39
- raise NotImplementedError
40
- end
41
-
42
- # @since 0.2.0
43
- def parse(body)
44
- Hash.new
45
- end
46
-
47
- private
48
- # @since 0.2.0
49
- # @api private
50
- def self.require_parser(parser)
51
- require "hanami/routing/parsing/#{ parser }_parser"
52
-
53
- parser = Utils::String.classify(parser)
54
- Utils::Class.load!("Hanami::Routing::Parsing::#{ parser }Parser").new
55
- rescue LoadError, NameError
56
- raise UnknownParserError.new(parser)
57
- end
58
- end
59
- end
60
- end
61
- end
@@ -1,71 +0,0 @@
1
- require 'http_router/route'
2
-
3
- module Hanami
4
- module Routing
5
- # Entry of the routing system
6
- #
7
- # @api private
8
- #
9
- # @since 0.1.0
10
- # @api private
11
- #
12
- # @see http://rdoc.info/gems/http_router/HttpRouter/Route
13
- #
14
- # @example
15
- # require 'hanami/router'
16
- #
17
- # router = Hanami::Router.new
18
- # router.get('/', to: endpoint) # => #<Hanami::Routing::Route:0x007f83083ba028 ...>
19
- class Route < HttpRouter::Route
20
- # @since 0.7.0
21
- # @api private
22
- def initialize(*)
23
- super
24
- @name = nil
25
- end
26
-
27
- # Asks the given resolver to return an endpoint that will be associated
28
- # with the other options.
29
- #
30
- # @param resolver [Hanami::Routing::EndpointResolver, #resolve] this may change
31
- # according to the :resolve option passed to Hanami::Router#initialize.
32
- #
33
- # @param options [Hash] options to customize the route
34
- # @option options [Symbol] :as the name we want to use for the route
35
- #
36
- # @since 0.1.0
37
- #
38
- # @api private
39
- #
40
- # @see Hanami::Router#initialize
41
- #
42
- # @example
43
- # require 'hanami/router'
44
- #
45
- # router = Hanami::Router.new
46
- # router.get('/', to: endpoint, as: :home_page).name # => :home_page
47
- #
48
- # router.path(:home_page) # => '/'
49
- def generate(resolver, options = {}, &endpoint)
50
- self.to = resolver.resolve(options, &endpoint)
51
- self.name = options[:as].to_sym if options[:as]
52
- self
53
- end
54
-
55
- # Introspect the given route to understand if there is a wrapped
56
- # router that has an inspector
57
- #
58
- # @since 0.2.0
59
- # @api private
60
- def nested_router
61
- dest.routes if dest.respond_to?(:routes) && dest.routes.respond_to?(:inspector)
62
- end
63
-
64
- private
65
- # @api private
66
- def to=(dest = nil, &blk)
67
- self.to dest, &blk
68
- end
69
- end
70
- end
71
- end