http_router 0.8.11 → 0.9.3
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.
- data/Rakefile +32 -3
- data/js/lib/http_router.coffee +368 -0
- data/js/lib/http_router.js +668 -0
- data/js/package.json +10 -0
- data/js/test/test.coffee +136 -0
- data/js/test/test.js +229 -0
- data/lib/http_router/node/arbitrary.rb +1 -1
- data/lib/http_router/node/free_regex.rb +3 -2
- data/lib/http_router/node/glob.rb +4 -3
- data/lib/http_router/node/glob_regex.rb +3 -2
- data/lib/http_router/node/lookup.rb +2 -3
- data/lib/http_router/node/path.rb +62 -0
- data/lib/http_router/node/request.rb +13 -2
- data/lib/http_router/node/root.rb +29 -2
- data/lib/http_router/node/spanning_regex.rb +6 -5
- data/lib/http_router/node.rb +7 -12
- data/lib/http_router/rack/builder.rb +0 -8
- data/lib/http_router/regex_route.rb +13 -0
- data/lib/http_router/route.rb +57 -42
- data/lib/http_router/util.rb +41 -0
- data/lib/http_router/version.rb +1 -1
- data/lib/http_router.rb +17 -22
- data/test/common/generate.txt +8 -2
- data/test/common/http_recognize.txt +58 -0
- data/test/common/recognize.txt +12 -65
- data/test/generation.rb +5 -102
- data/test/generic.rb +111 -0
- data/test/recognition.rb +6 -100
- data/test/test_misc.rb +26 -2
- data/test/test_mounting.rb +4 -4
- data/test/test_recognition.rb +18 -0
- metadata +94 -34
- data/lib/http_router/node/destination.rb +0 -45
- data/lib/http_router/path.rb +0 -58
@@ -3,6 +3,8 @@ class HttpRouter
|
|
3
3
|
def initialize(router, path, opts = {})
|
4
4
|
@router, @original_path, @opts = router, path, opts
|
5
5
|
@param_names = @original_path.respond_to?(:names) ? @original_path.names.map(&:to_sym) : []
|
6
|
+
@path_validation_regex = original_path
|
7
|
+
Util.add_path_generation(self, self, opts.delete(:path_for_generation), @original_path) if opts.key?(:path_for_generation)
|
6
8
|
process_opts
|
7
9
|
end
|
8
10
|
|
@@ -22,5 +24,16 @@ class HttpRouter
|
|
22
24
|
def regex?
|
23
25
|
true
|
24
26
|
end
|
27
|
+
|
28
|
+
def generate_from?(params)
|
29
|
+
false
|
30
|
+
end
|
31
|
+
|
32
|
+
def url_with_params(*a)
|
33
|
+
url_args_processing(a) do |args, options|
|
34
|
+
respond_to?(:raw_url) or raise InvalidRouteException
|
35
|
+
raw_url(args, options)
|
36
|
+
end
|
37
|
+
end
|
25
38
|
end
|
26
39
|
end
|
data/lib/http_router/route.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
class HttpRouter
|
2
2
|
class Route
|
3
|
-
DoubleCompileError = Class.new(RuntimeError)
|
4
|
-
|
5
3
|
attr_reader :default_values, :router, :path, :conditions, :original_path, :match_partially, :dest, :regex, :named, :matches_with
|
6
4
|
alias_method :match_partially?, :match_partially
|
7
5
|
alias_method :regex?, :regex
|
8
6
|
|
9
7
|
def initialize(router, path, opts = {})
|
10
8
|
@router, @original_path, @opts = router, path, opts
|
11
|
-
if @original_path
|
9
|
+
if @original_path
|
10
|
+
@match_partially = true and path.slice!(-1) if @original_path[/[^\\]\*$/]
|
11
|
+
@original_path[0, 0] = '/' if @original_path[0] != ?/
|
12
|
+
else
|
12
13
|
@match_partially = true
|
13
|
-
path.slice!(-1)
|
14
14
|
end
|
15
15
|
process_opts
|
16
16
|
end
|
@@ -26,6 +26,7 @@ class HttpRouter
|
|
26
26
|
@match_partially = @opts[:__partial__] if @match_partially.nil? && !@opts[:__partial__].nil?
|
27
27
|
@match_partially = @opts[:partial] if @match_partially.nil? && !@opts[:partial].nil?
|
28
28
|
name(@opts[:__name__] || @opts[:name]) if @opts.key?(:__name__) || @opts.key?(:name)
|
29
|
+
@needed_keys = significant_variable_names - @default_values.keys
|
29
30
|
end
|
30
31
|
|
31
32
|
def as_options
|
@@ -49,24 +50,30 @@ class HttpRouter
|
|
49
50
|
|
50
51
|
def name(n)
|
51
52
|
@named = n
|
52
|
-
@router.named_routes[n]
|
53
|
+
@router.named_routes[n] << self
|
54
|
+
@router.named_routes[n].sort!{|r1, r2| r2.significant_variable_names.size <=> r1.significant_variable_names.size }
|
53
55
|
self
|
54
56
|
end
|
55
57
|
|
56
|
-
def request_method(
|
57
|
-
(
|
58
|
+
def request_method(*method)
|
59
|
+
add_to_contitions(:request_method, method)
|
60
|
+
end
|
61
|
+
|
62
|
+
def host(*host)
|
63
|
+
add_to_contitions(:host, host)
|
58
64
|
end
|
59
65
|
|
60
|
-
def
|
61
|
-
(
|
66
|
+
def scheme(*scheme)
|
67
|
+
add_to_contitions(:scheme, scheme)
|
62
68
|
end
|
63
69
|
|
64
|
-
def
|
65
|
-
(
|
70
|
+
def user_agent(*user_agent)
|
71
|
+
add_to_contitions(:user_agent, user_agent)
|
66
72
|
end
|
67
73
|
|
68
|
-
def
|
69
|
-
((@conditions ||= {})[
|
74
|
+
def add_to_contitions(name, *vals)
|
75
|
+
((@conditions ||= {})[name] ||= []).concat(vals.flatten)
|
76
|
+
self
|
70
77
|
end
|
71
78
|
|
72
79
|
def matching(matchers)
|
@@ -101,13 +108,15 @@ class HttpRouter
|
|
101
108
|
self
|
102
109
|
end
|
103
110
|
|
104
|
-
def post; request_method('POST');
|
105
|
-
def get; request_method('GET');
|
106
|
-
def put; request_method('PUT');
|
107
|
-
def delete; request_method('DELETE');
|
108
|
-
def head; request_method('HEAD');
|
109
|
-
def options; request_method('OPTIONS');
|
110
|
-
def patch; request_method('PATCH');
|
111
|
+
def post; request_method('POST'); end
|
112
|
+
def get; request_method('GET'); end
|
113
|
+
def put; request_method('PUT'); end
|
114
|
+
def delete; request_method('DELETE'); end
|
115
|
+
def head; request_method('HEAD'); end
|
116
|
+
def options; request_method('OPTIONS'); end
|
117
|
+
def patch; request_method('PATCH'); end
|
118
|
+
def trace; request_method('TRACE'); end
|
119
|
+
def conenct; request_method('CONNECT'); end
|
111
120
|
|
112
121
|
def arbitrary(blk = nil, &blk2)
|
113
122
|
arbitrary_with_continue { |req, params|
|
@@ -129,19 +138,25 @@ class HttpRouter
|
|
129
138
|
Route.new(new_router, @original_path.dup, as_options)
|
130
139
|
end
|
131
140
|
|
132
|
-
def url_with_params(*
|
141
|
+
def url_with_params(*a)
|
142
|
+
url_args_processing(a) do |args, options|
|
143
|
+
path = args.empty? ? matching_path(options) : matching_path(args, options)
|
144
|
+
raise InvalidRouteException unless path
|
145
|
+
path.url(args, options)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def url_args_processing(args)
|
133
150
|
options = args.last.is_a?(Hash) ? args.pop : nil
|
134
151
|
options = options.nil? ? default_values.dup : default_values.merge(options) if default_values
|
135
152
|
options.delete_if{ |k,v| v.nil? } if options
|
136
|
-
|
137
|
-
raise InvalidRouteException unless path
|
138
|
-
result, params = path.url(args, options)
|
153
|
+
result, params = yield args, options
|
139
154
|
mount_point = router.url_mount && router.url_mount.url(options)
|
140
155
|
mount_point ? [File.join(mount_point, result), params] : [result, params]
|
141
156
|
end
|
142
157
|
|
143
158
|
def significant_variable_names
|
144
|
-
@significant_variable_names ||= @original_path.scan(/(^|[^\\])[:\*]([a-zA-Z0-9_]+)/).map{|p| p.last.to_sym}
|
159
|
+
@significant_variable_names ||= @original_path.nil? ? [] : @original_path.scan(/(^|[^\\])[:\*]([a-zA-Z0-9_]+)/).map{|p| p.last.to_sym}
|
145
160
|
end
|
146
161
|
|
147
162
|
def matching_path(params, other_hash = nil)
|
@@ -161,6 +176,7 @@ class HttpRouter
|
|
161
176
|
|
162
177
|
private
|
163
178
|
def raw_paths
|
179
|
+
return [] if @original_path.nil?
|
164
180
|
@raw_paths ||= begin
|
165
181
|
start_index, end_index = 0, 1
|
166
182
|
@raw_paths, chars = [""], @original_path.split('')
|
@@ -226,24 +242,27 @@ class HttpRouter
|
|
226
242
|
def add_path_to_tree
|
227
243
|
raise DoubleCompileError if compiled?
|
228
244
|
@paths ||= begin
|
229
|
-
raw_paths.
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
245
|
+
if raw_paths.empty?
|
246
|
+
add_non_path_to_tree(@router.root, nil, [])
|
247
|
+
else
|
248
|
+
raw_paths.map do |path|
|
249
|
+
param_names = []
|
250
|
+
node = @router.root
|
251
|
+
path.split(/\//).each do |part|
|
252
|
+
next if part == ''
|
253
|
+
parts = part.scan(/\\.|[:*][a-z0-9_]+|[^:*\\]+/)
|
254
|
+
node = parts.size == 1 ? add_normal_part(node, part, param_names) : add_complex_part(node, parts, param_names)
|
255
|
+
end
|
256
|
+
add_non_path_to_tree(node, path, param_names)
|
236
257
|
end
|
237
|
-
add_non_path_to_tree(node, path, param_names)
|
238
258
|
end
|
239
259
|
end
|
240
260
|
end
|
241
261
|
|
242
262
|
def add_non_path_to_tree(node, path, names)
|
243
|
-
path_obj = Path.new(self, path, names)
|
244
263
|
node = node.add_request(@conditions) unless @conditions.empty?
|
245
264
|
@arbitrary.each{|a| node = node.add_arbitrary(a, match_partially?, names)} if @arbitrary
|
246
|
-
node.add_destination(
|
265
|
+
path_obj = node.add_destination(self, path, names)
|
247
266
|
if dest.respond_to?(:url_mount=)
|
248
267
|
urlmount = UrlMount.new(@original_path, @default_values)
|
249
268
|
urlmount.url_mount = router.url_mount if router.url_mount
|
@@ -254,13 +273,9 @@ class HttpRouter
|
|
254
273
|
|
255
274
|
def append_querystring_value(uri, key, value)
|
256
275
|
case value
|
257
|
-
when Array
|
258
|
-
|
259
|
-
|
260
|
-
when Hash
|
261
|
-
value.each{ |k, v| append_querystring_value(uri, "#{key}[#{k}]", v) }
|
262
|
-
else
|
263
|
-
uri << '&' << CGI.escape(key.to_s) << '=' << CGI.escape(value.to_s)
|
276
|
+
when Array then value.each{ |v| append_querystring_value(uri, "#{key}[]", v) }
|
277
|
+
when Hash then value.each{ |k, v| append_querystring_value(uri, "#{key}[#{k}]", v) }
|
278
|
+
else uri << '&' << CGI.escape(key.to_s) << '=' << CGI.escape(value.to_s)
|
264
279
|
end
|
265
280
|
end
|
266
281
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class HttpRouter
|
2
|
+
module Util
|
3
|
+
def self.add_path_generation(target, route, path, path_validation_regex = nil)
|
4
|
+
regex_parts = path.split(/([:\*][a-zA-Z0-9_]+)/)
|
5
|
+
regex, code = '', ''
|
6
|
+
dynamic = false
|
7
|
+
regex_parts.each_with_index do |part, index|
|
8
|
+
case part[0]
|
9
|
+
when ?:, ?*
|
10
|
+
if index != 0 && regex_parts[index - 1][-1] == ?\\
|
11
|
+
regex << Regexp.quote(part) unless path_validation_regex
|
12
|
+
code << part
|
13
|
+
dynamic = true
|
14
|
+
else
|
15
|
+
regex << (route.matches_with[part[1, part.size].to_sym] || '.*?').to_s unless path_validation_regex
|
16
|
+
code << "\#{args.shift || (options && options.delete(:#{part[1, part.size]})) || return}"
|
17
|
+
dynamic = true
|
18
|
+
end
|
19
|
+
else
|
20
|
+
regex << Regexp.quote(part) unless path_validation_regex
|
21
|
+
code << part
|
22
|
+
end
|
23
|
+
end
|
24
|
+
path_validation_regex ||= Regexp.new("^#{regex}$") if dynamic
|
25
|
+
if path_validation_regex
|
26
|
+
target.instance_eval <<-EOT, __FILE__, __LINE__ + 1
|
27
|
+
def raw_url(args, options)
|
28
|
+
url = \"#{code}\"
|
29
|
+
#{path_validation_regex.inspect}.match(url) ? url : nil
|
30
|
+
end
|
31
|
+
EOT
|
32
|
+
else
|
33
|
+
target.instance_eval <<-EOT, __FILE__, __LINE__ + 1
|
34
|
+
def raw_url(args, options)
|
35
|
+
\"#{code}\"
|
36
|
+
end
|
37
|
+
EOT
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/http_router/version.rb
CHANGED
data/lib/http_router.rb
CHANGED
@@ -7,9 +7,9 @@ require 'http_router/node'
|
|
7
7
|
require 'http_router/request'
|
8
8
|
require 'http_router/response'
|
9
9
|
require 'http_router/route'
|
10
|
-
require 'http_router/path'
|
11
10
|
require 'http_router/rack'
|
12
11
|
require 'http_router/regex_route'
|
12
|
+
require 'http_router/util'
|
13
13
|
|
14
14
|
class HttpRouter
|
15
15
|
|
@@ -20,6 +20,10 @@ class HttpRouter
|
|
20
20
|
InvalidRouteException = Class.new(RuntimeError)
|
21
21
|
# Raised when a Route is not able to be generated due to a missing parameter.
|
22
22
|
MissingParameterException = Class.new(RuntimeError)
|
23
|
+
# Raised when a Route is compiled twice
|
24
|
+
DoubleCompileError = Class.new(RuntimeError)
|
25
|
+
# Raised an invalid request value is used
|
26
|
+
InvalidRequestValueError = Class.new(RuntimeError)
|
23
27
|
|
24
28
|
# Creates a new HttpRouter.
|
25
29
|
# Can be called with either <tt>HttpRouter.new(proc{|env| ... }, { .. options .. })</tt> or with the first argument omitted.
|
@@ -36,7 +40,6 @@ class HttpRouter
|
|
36
40
|
@ignore_trailing_slash = options && options.key?(:ignore_trailing_slash) ? options[:ignore_trailing_slash] : true
|
37
41
|
@redirect_trailing_slash = options && options.key?(:redirect_trailing_slash) ? options[:redirect_trailing_slash] : false
|
38
42
|
@known_methods = Set.new(options && options[:known_methods] || [])
|
39
|
-
@counter = 0
|
40
43
|
reset!
|
41
44
|
instance_eval(&blk) if blk
|
42
45
|
end
|
@@ -53,10 +56,12 @@ class HttpRouter
|
|
53
56
|
#
|
54
57
|
# Routes can also contain optional parts. There are surrounded with <tt>( )</tt>'s. If you need to match on a bracket in the route itself, you can escape the parentheses with a backslash.
|
55
58
|
#
|
56
|
-
#
|
59
|
+
# As well, options can be passed in that modify the route in further ways. See HttpRouter::Route#with_options for details. Typically, you want to add further options to the route by calling additional methods on it. See HttpRouter::Route for further details.
|
57
60
|
#
|
58
61
|
# Returns the route object.
|
59
|
-
def add(
|
62
|
+
def add(*args, &app)
|
63
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
64
|
+
path = args.first
|
60
65
|
route = add_route((Regexp === path ? RegexRoute : Route).new(self, path, opts))
|
61
66
|
route.to(app) if app
|
62
67
|
route
|
@@ -97,6 +102,7 @@ class HttpRouter
|
|
97
102
|
# Returns the route object.
|
98
103
|
def options(path, opts = {}, &app); add_with_request_method(path, :options, opts, &app); end
|
99
104
|
|
105
|
+
# Performs recoginition without actually calling the application.
|
100
106
|
def recognize(env)
|
101
107
|
call(env, false)
|
102
108
|
end
|
@@ -121,7 +127,7 @@ class HttpRouter
|
|
121
127
|
|
122
128
|
# Resets the router to a clean state.
|
123
129
|
def reset!
|
124
|
-
@routes, @named_routes, @root = [], {}, Node::Root.new(self)
|
130
|
+
@routes, @named_routes, @root = [], Hash.new{|h,k| h[k] = []}, Node::Root.new(self)
|
125
131
|
@default_app = Proc.new{ |env| ::Rack::Response.new("Your request couldn't be found", 404).finish }
|
126
132
|
end
|
127
133
|
|
@@ -146,16 +152,19 @@ class HttpRouter
|
|
146
152
|
# # ==> "/123.html?fun=inthesun"
|
147
153
|
def url(route, *args)
|
148
154
|
case route
|
149
|
-
when Symbol then @named_routes.key?(route)
|
150
|
-
when Route then route.url(*args)
|
151
|
-
else raise InvalidRouteException
|
155
|
+
when Symbol then @named_routes.key?(route) && @named_routes[route].each{|r| url = r.url(*args); return url if url}
|
156
|
+
when Route then return route.url(*args)
|
152
157
|
end
|
158
|
+
raise(InvalidRouteException)
|
153
159
|
end
|
154
160
|
|
161
|
+
# This method is invoked when a Path object gets called with an env. Override it to implement custom path processing.
|
155
162
|
def process_destination_path(path, env)
|
156
163
|
path.route.dest.call(env)
|
157
164
|
end
|
158
165
|
|
166
|
+
# This method defines what sort of responses are considered "passes", and thus, route processing will continue. Override
|
167
|
+
# it to implement custom passing.
|
159
168
|
def pass_on_response(response)
|
160
169
|
response[1]['X-Cascade'] == 'pass'
|
161
170
|
end
|
@@ -170,16 +179,6 @@ class HttpRouter
|
|
170
179
|
@redirect_trailing_slash
|
171
180
|
end
|
172
181
|
|
173
|
-
def rewrite_partial_path_info(env, request)
|
174
|
-
env['PATH_INFO'] = "/#{request.path.join('/')}"
|
175
|
-
env['SCRIPT_NAME'] += request.rack_request.path_info[0, request.rack_request.path_info.size - env['PATH_INFO'].size]
|
176
|
-
end
|
177
|
-
|
178
|
-
def rewrite_path_info(env, request)
|
179
|
-
env['SCRIPT_NAME'] += request.rack_request.path_info
|
180
|
-
env['PATH_INFO'] = ''
|
181
|
-
end
|
182
|
-
|
183
182
|
# Creates a deep-copy of the router.
|
184
183
|
def clone(klass = self.class)
|
185
184
|
cloned_router = klass.new(@options)
|
@@ -196,10 +195,6 @@ class HttpRouter
|
|
196
195
|
cloned_router
|
197
196
|
end
|
198
197
|
|
199
|
-
def next_counter
|
200
|
-
@counter += 1
|
201
|
-
end
|
202
|
-
|
203
198
|
private
|
204
199
|
def no_response(env, perform_call = true)
|
205
200
|
supported_methods = @known_methods.select do |m|
|
data/test/common/generate.txt
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
{"a": "/:var"}
|
2
|
+
["/test", "a", {"var":"test"}]
|
3
|
+
# ["/test", "a", ["test"]]
|
4
|
+
|
1
5
|
{"a": "/"}
|
2
6
|
{"b": "/test"}
|
3
7
|
{"c": "/test/time"}
|
@@ -72,10 +76,12 @@
|
|
72
76
|
["/1/123", "a", {"entry": "123"}]
|
73
77
|
|
74
78
|
{"a": "/:var"}
|
75
|
-
["/%C3%A4", "a", "ä"]
|
79
|
+
["/%C3%A4", "a", ["ä"]]
|
80
|
+
["/%C3%A4", "a", {"var": "ä"}]
|
76
81
|
|
77
82
|
{"a": {"path": ":var", "var": {"regex": "\\d+"}}}
|
78
|
-
|
83
|
+
[null, "a", "asd"]
|
84
|
+
["/123", "a", "123"]
|
79
85
|
|
80
86
|
{"a": "/var"}
|
81
87
|
["/var?foo%5B%5D=baz&foo%5B%5D=bar", "a", {"foo": ["baz", "bar"]}]
|
@@ -0,0 +1,58 @@
|
|
1
|
+
{"nothing":{"path":"/", "conditions": {"request_method": "GET"}}}
|
2
|
+
{"post":{"path":"/test", "conditions": {"request_method": "POST"}}}
|
3
|
+
{"put":{"path":"/test", "conditions": {"request_method": "PUT"}}}
|
4
|
+
["post", {"path": "/test", "method": "POST"}]
|
5
|
+
[[405, {"Allow": "POST, PUT"}], {"path": "/test", "method": "GET"}]
|
6
|
+
|
7
|
+
{"router": {"path": "/test", "conditions": {"request_method": ["POST", "GET"]}}}
|
8
|
+
["router", {"path": "/test", "method": "POST"}]
|
9
|
+
["router", {"path": "/test", "method": "GET"}]
|
10
|
+
[[405, {"Allow": "GET, POST"}], {"path": "/test", "method": "PUT"}]
|
11
|
+
|
12
|
+
{"get": {"path": "/test(.:format)", "conditions": {"request_method": "GET"}}}
|
13
|
+
{"post": {"path": "/test(.:format)", "conditions": {"request_method": "POST"}}}
|
14
|
+
{"delete": {"path": "/test(.:format)", "conditions": {"request_method": "DELETE"}}}
|
15
|
+
["get", {"path": "/test", "method": "GET"}]
|
16
|
+
["post", {"path": "/test", "method": "POST"}]
|
17
|
+
["delete", {"path": "/test", "method": "DELETE"}]
|
18
|
+
["get", {"path": "/test.html", "method": "GET"}, {"format": "html"}]
|
19
|
+
["post", {"path": "/test.html", "method": "POST"}, {"format": "html"}]
|
20
|
+
["delete", {"path": "/test.html", "method": "DELETE"}, {"format": "html"}]
|
21
|
+
[[405, {"Allow": "DELETE, GET, POST"}], {"path": "/test", "method": "PUT"}]
|
22
|
+
|
23
|
+
{"post": {"path": "/test", "conditions": {"request_method": "POST"}}}
|
24
|
+
{"post_2": {"path": "/test/post", "conditions": {"request_method": "POST"}}}
|
25
|
+
{"get": {"path": "/test", "conditions": {"request_method": "GET"}}}
|
26
|
+
{"get_2": {"path": "/test/post", "conditions": {"request_method": "GET"}}}
|
27
|
+
{"any_2": "/test/post"}
|
28
|
+
{"any": "/test"}
|
29
|
+
["post", {"path": "/test", "method": "POST"}]
|
30
|
+
["get", {"path": "/test", "method": "GET"}]
|
31
|
+
["any", {"path": "/test", "method": "PUT"}]
|
32
|
+
["post_2", {"path": "/test/post", "method": "POST"}]
|
33
|
+
["get_2", {"path": "/test/post", "method": "GET"}]
|
34
|
+
["any_2", {"path": "/test/post", "method": "PUT"}]
|
35
|
+
|
36
|
+
{"post": {"path": "/test", "conditions": {"request_method": "POST"}}}
|
37
|
+
{"any": "/test"}
|
38
|
+
["post", {"path": "/test", "method": "POST"}]
|
39
|
+
["any", {"path": "/test", "method": "PUT"}]
|
40
|
+
|
41
|
+
{"host2_post": {"path": "/test", "conditions": {"request_method": "POST", "host": "host2"}}}
|
42
|
+
{"host2_get": {"path": "/test", "conditions": {"request_method": "GET", "host": "host2"}}}
|
43
|
+
{"host2": {"path": "/test", "conditions": {"host": "host2"}}}
|
44
|
+
{"post": {"path": "/test", "conditions": {"request_method": "POST"}}}
|
45
|
+
["host2", {"path": "http://host2/test", "method": "PUT"}]
|
46
|
+
["post", {"path": "http://host1/test", "method": "POST"}]
|
47
|
+
["host2_get", {"path": "http://host2/test", "method": "GET"}]
|
48
|
+
["host2_post", {"path": "http://host2/test", "method": "POST"}]
|
49
|
+
|
50
|
+
{"with": {"path": "/test", "conditions": {"request_method": "GET", "host": {"regex": "host1"}}}}
|
51
|
+
{"without": {"path": "/test", "conditions": {"request_method": "GET"}}}
|
52
|
+
["without", "http://host2/test"]
|
53
|
+
["with", "http://host2.host1.com/test"]
|
54
|
+
|
55
|
+
{"http": {"path": "/test", "conditions": {"scheme": "http"}}}
|
56
|
+
{"https": {"path": "/test", "conditions": {"scheme": "https"}}}
|
57
|
+
["http", {"path": "/test", "scheme": "http"}]
|
58
|
+
["https", {"path": "/test", "scheme": "https"}]
|
data/test/common/recognize.txt
CHANGED
@@ -38,6 +38,9 @@
|
|
38
38
|
["route", "/test.html", {"format": "html"}]
|
39
39
|
["route", "/test"]
|
40
40
|
|
41
|
+
{"route": "/"}
|
42
|
+
["route", "/"]
|
43
|
+
|
41
44
|
[{"route": "(.:format)"}]
|
42
45
|
["route", "/.html", {"format": "html"}]
|
43
46
|
["route", "/"]
|
@@ -160,6 +163,9 @@
|
|
160
163
|
[{"route": "test\\*variable"}]
|
161
164
|
["route", "/test*variable"]
|
162
165
|
|
166
|
+
[{"route": "testvariable\\*"}]
|
167
|
+
["route", "/testvariable*"]
|
168
|
+
|
163
169
|
[{"route": "/føø"}]
|
164
170
|
["route", "/f%C3%B8%C3%B8"]
|
165
171
|
|
@@ -176,16 +182,16 @@
|
|
176
182
|
["test", "/test/optional/", {"PATH_INFO": "/optional/"}]
|
177
183
|
["root", "/testing/optional", {"PATH_INFO": "/testing/optional"}]
|
178
184
|
|
179
|
-
|
180
|
-
["route", "one-value-time", {"variable": "value"}]
|
185
|
+
{"route": "/one-:variable-time"}
|
186
|
+
["route", "/one-value-time", {"variable": "value"}]
|
181
187
|
|
182
188
|
[{"route": {"path": "/one-:variable-time", "variable": {"regex": "\\d+"}}}]
|
183
|
-
["route", "one-123-time", {"variable": "123"}]
|
184
|
-
[null, "one-value-time"]
|
189
|
+
["route", "/one-123-time", {"variable": "123"}]
|
190
|
+
[null, "/one-value-time"]
|
185
191
|
|
186
192
|
[{"route": {"path": "/one-:variable-time", "variable": {"regex": "\\d+"}}}]
|
187
|
-
["route", "one-123-time", {"variable": "123"}]
|
188
|
-
[null, "one-value-time"]
|
193
|
+
["route", "/one-123-time", {"variable": "123"}]
|
194
|
+
[null, "/one-value-time"]
|
189
195
|
|
190
196
|
[{"route": "hey.:greed.html"}]
|
191
197
|
["route", "/hey.greedybody.html", {"greed": "greedybody"}]
|
@@ -202,62 +208,3 @@
|
|
202
208
|
{"without_regex": "/:common_variable.:unmatched"}
|
203
209
|
["with_regex", "/common.123", {"common_variable": "common", "matched": "123"}]
|
204
210
|
["without_regex", "/common.other", {"common_variable": "common", "unmatched": "other"}]
|
205
|
-
|
206
|
-
{"nothing":{"path":"/", "conditions": {"request_method": "GET"}}}
|
207
|
-
{"post":{"path":"/test", "conditions": {"request_method": "POST"}}}
|
208
|
-
{"put":{"path":"/test", "conditions": {"request_method": "PUT"}}}
|
209
|
-
["post", {"path": "/test", "method": "POST"}]
|
210
|
-
[[405, {"Allow": "POST, PUT"}], {"path": "/test", "method": "GET"}]
|
211
|
-
|
212
|
-
{"router": {"path": "/test", "conditions": {"request_method": ["POST", "GET"]}}}
|
213
|
-
["router", {"path": "/test", "method": "POST"}]
|
214
|
-
["router", {"path": "/test", "method": "GET"}]
|
215
|
-
[[405, {"Allow": "GET, POST"}], {"path": "/test", "method": "PUT"}]
|
216
|
-
|
217
|
-
{"get": {"path": "/test(.:format)", "conditions": {"request_method": "GET"}}}
|
218
|
-
{"post": {"path": "/test(.:format)", "conditions": {"request_method": "POST"}}}
|
219
|
-
{"delete": {"path": "/test(.:format)", "conditions": {"request_method": "DELETE"}}}
|
220
|
-
["get", {"path": "/test", "method": "GET"}]
|
221
|
-
["post", {"path": "/test", "method": "POST"}]
|
222
|
-
["delete", {"path": "/test", "method": "DELETE"}]
|
223
|
-
["get", {"path": "/test.html", "method": "GET"}, {"format": "html"}]
|
224
|
-
["post", {"path": "/test.html", "method": "POST"}, {"format": "html"}]
|
225
|
-
["delete", {"path": "/test.html", "method": "DELETE"}, {"format": "html"}]
|
226
|
-
[[405, {"Allow": "DELETE, GET, POST"}], {"path": "/test", "method": "PUT"}]
|
227
|
-
|
228
|
-
{"post": {"path": "/test", "conditions": {"request_method": "POST"}}}
|
229
|
-
{"post_2": {"path": "/test/post", "conditions": {"request_method": "POST"}}}
|
230
|
-
{"get": {"path": "/test", "conditions": {"request_method": "GET"}}}
|
231
|
-
{"get_2": {"path": "/test/post", "conditions": {"request_method": "GET"}}}
|
232
|
-
{"any_2": "/test/post"}
|
233
|
-
{"any": "/test"}
|
234
|
-
["post", {"path": "/test", "method": "POST"}]
|
235
|
-
["get", {"path": "/test", "method": "GET"}]
|
236
|
-
["any", {"path": "/test", "method": "PUT"}]
|
237
|
-
["post_2", {"path": "/test/post", "method": "POST"}]
|
238
|
-
["get_2", {"path": "/test/post", "method": "GET"}]
|
239
|
-
["any_2", {"path": "/test/post", "method": "PUT"}]
|
240
|
-
|
241
|
-
{"post": {"path": "/test", "conditions": {"request_method": "POST"}}}
|
242
|
-
{"any": "/test"}
|
243
|
-
["post", {"path": "/test", "method": "POST"}]
|
244
|
-
["any", {"path": "/test", "method": "PUT"}]
|
245
|
-
|
246
|
-
{"host2_post": {"path": "/test", "conditions": {"request_method": "POST", "host": "host2"}}}
|
247
|
-
{"host2_get": {"path": "/test", "conditions": {"request_method": "GET", "host": "host2"}}}
|
248
|
-
{"host2": {"path": "/test", "conditions": {"host": "host2"}}}
|
249
|
-
{"post": {"path": "/test", "conditions": {"request_method": "POST"}}}
|
250
|
-
["host2", {"path": "http://host2/test", "method": "PUT"}]
|
251
|
-
["post", {"path": "http://host1/test", "method": "POST"}]
|
252
|
-
["host2_get", {"path": "http://host2/test", "method": "GET"}]
|
253
|
-
["host2_post", {"path": "http://host2/test", "method": "POST"}]
|
254
|
-
|
255
|
-
{"with": {"path": "/test", "conditions": {"request_method": "GET", "host": {"regex": "host1"}}}}
|
256
|
-
{"without": {"path": "/test", "conditions": {"request_method": "GET"}}}
|
257
|
-
["without", "http://host2/test"]
|
258
|
-
["with", "http://host2.host1.com/test"]
|
259
|
-
|
260
|
-
{"http": {"path": "/test", "conditions": {"scheme": "http"}}}
|
261
|
-
{"https": {"path": "/test", "conditions": {"scheme": "https"}}}
|
262
|
-
["http", {"path": "/test", "scheme": "http"}]
|
263
|
-
["https", {"path": "/test", "scheme": "https"}]
|