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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -3
- data/README.md +192 -154
- data/hanami-router.gemspec +23 -20
- data/lib/hanami/middleware/body_parser.rb +17 -13
- data/lib/hanami/middleware/body_parser/class_interface.rb +56 -56
- data/lib/hanami/middleware/body_parser/errors.rb +7 -4
- data/lib/hanami/middleware/body_parser/json_parser.rb +5 -3
- data/lib/hanami/middleware/error.rb +16 -0
- data/lib/hanami/router.rb +262 -149
- data/lib/hanami/router/version.rb +3 -1
- data/lib/hanami/routing.rb +193 -0
- data/lib/hanami/routing/endpoint.rb +122 -104
- data/lib/hanami/routing/endpoint_resolver.rb +20 -16
- data/lib/hanami/routing/prefix.rb +102 -0
- data/lib/hanami/routing/recognized_route.rb +40 -26
- data/lib/hanami/routing/resource.rb +9 -7
- data/lib/hanami/routing/resource/action.rb +58 -33
- data/lib/hanami/routing/resource/nested.rb +4 -1
- data/lib/hanami/routing/resource/options.rb +3 -1
- data/lib/hanami/routing/resources.rb +6 -4
- data/lib/hanami/routing/resources/action.rb +11 -6
- data/lib/hanami/routing/routes_inspector.rb +22 -20
- data/lib/hanami/routing/scope.rb +112 -0
- metadata +47 -25
- data/lib/hanami-router.rb +0 -1
- data/lib/hanami/routing/error.rb +0 -7
- data/lib/hanami/routing/force_ssl.rb +0 -212
- data/lib/hanami/routing/http_router.rb +0 -220
- data/lib/hanami/routing/http_router_monkey_patch.rb +0 -38
- data/lib/hanami/routing/namespace.rb +0 -98
- data/lib/hanami/routing/parsers.rb +0 -113
- data/lib/hanami/routing/parsing/json_parser.rb +0 -33
- data/lib/hanami/routing/parsing/parser.rb +0 -61
- 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
|
data/lib/hanami/routing/route.rb
DELETED
@@ -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
|