hanami-router 1.3.2 → 2.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
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