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.
- 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
|