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.
@@ -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
@@ -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[-1] == ?*
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] = self
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(m)
57
- ((@conditions ||= {})[:request_method] ||= []) << m; self
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 host(host)
61
- ((@conditions ||= {})[:host] ||= []) << host; self
66
+ def scheme(*scheme)
67
+ add_to_contitions(:scheme, scheme)
62
68
  end
63
69
 
64
- def scheme(scheme)
65
- ((@conditions ||= {})[:scheme] ||= []) << scheme; self
70
+ def user_agent(*user_agent)
71
+ add_to_contitions(:user_agent, user_agent)
66
72
  end
67
73
 
68
- def user_agent(user_agent)
69
- ((@conditions ||= {})[:user_agent] ||= []) << user_agent; self
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'); end
105
- def get; request_method('GET'); end
106
- def put; request_method('PUT'); end
107
- def delete; request_method('DELETE'); end
108
- def head; request_method('HEAD'); end
109
- def options; request_method('OPTIONS'); end
110
- def patch; request_method('PATCH'); end
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(*args)
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
- path = args.empty? ? matching_path(options) : matching_path(args, options)
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.map do |path|
230
- param_names = []
231
- node = @router.root
232
- path.split(/\//).each do |part|
233
- next if part == ''
234
- parts = part.scan(/\\.|[:*][a-z0-9_]+|[^:*\\]+/)
235
- node = parts.size == 1 ? add_normal_part(node, part, param_names) : add_complex_part(node, parts, param_names)
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(path_obj, @match_partially)
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
- k = "#{key}[]"
259
- value.each{ |v| append_querystring_value(uri, k, v) }
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
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  class HttpRouter #:nodoc
3
- VERSION = '0.8.11'
3
+ VERSION = '0.9.3'
4
4
  end
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
- # The second argument, options, is an optional hash that can 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.
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(path, opts = {}, &app)
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) ? @named_routes[route].url(*args) : raise(InvalidRouteException)
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|
@@ -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
- [null, "a", "asd"]
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"}]
@@ -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
- [{"route": "/one-:variable-time"}]
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"}]