http_router 0.8.11 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- 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"}]
|