Permalink
Browse files

allow nil paths for matching

  • Loading branch information...
joshbuddy committed Jul 24, 2011
1 parent a97320b commit a26d0dbcb048e6bb52dad7de214671fad2ee6342
Showing with 40 additions and 19 deletions.
  1. +3 −1 lib/http_router.rb
  2. +11 −7 lib/http_router/node/request.rb
  3. +17 −10 lib/http_router/route.rb
  4. +0 −1 test/common/recognize.txt
  5. +9 −0 test/test_recognition.rb
View
@@ -59,7 +59,9 @@ def initialize(*args, &blk)
# 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.
#
# Returns the route object.
- def add(path, opts = {}, &app)
+ def add(*args, &app)
+ opts = args.last.is_a?(Hash) ? args.pop : {}
+ path = args.first
route = add_route((Regexp === path ? RegexRoute : Route).new(self, path, opts))
route.to(app) if app
route
@@ -6,8 +6,18 @@ class Request < Node
attr_reader :request_method, :opts
def initialize(router, parent, opts)
+ opts.each do |k, v|
+ v = [v] unless v.is_a?(Array)
+ case k
+ when :request_method
+ v.map!{|val| val.to_s.upcase}
+ v.all?{|m| VALID_HTTP_VERBS.include?(m)} or raise InvalidRequestValueError, "Invalid value for request_method #{v.inspect}"
+ v.each{|val| router.known_methods << val}
+ end
+ opts[k] = v
+ end
@opts = opts
- Array(@opts[:request_method]).each { |m| router.known_methods << m } if @opts.key?(:request_method)
+ @opts[:request_method].each { |m| router.known_methods << m } if @opts.key?(:request_method)
super(router, parent)
end
@@ -18,12 +28,6 @@ def usable?(other)
def to_code
code = "if "
code << @opts.map do |k,v|
- v = [v] unless v.is_a?(Array)
- case k
- when :request_method
- v.map!{|vv| vv.to_s.upcase}
- v.all?{|m| VALID_HTTP_VERBS.include?(m)} or raise InvalidRequestValueError, "Invalid value for request_method #{v.inspect}"
- end
case v.size
when 1 then to_code_condition(k, v.first)
else "(#{v.map{|vv| to_code_condition(k, vv)}.join(' or ')})"
View
@@ -6,9 +6,11 @@ class Route
def initialize(router, path, opts = {})
@router, @original_path, @opts = router, path, opts
- if @original_path[-1] == ?*
+ if @original_path && @original_path[-1] == ?*
@match_partially = true
path.slice!(-1)
+ elsif @original_path.nil?
+ @match_partially = true
end
process_opts
end
@@ -148,7 +150,7 @@ def url_with_params(*args)
end
def significant_variable_names
- @significant_variable_names ||= @original_path.scan(/(^|[^\\])[:\*]([a-zA-Z0-9_]+)/).map{|p| p.last.to_sym}
+ @significant_variable_names ||= @original_path.nil? ? [] : @original_path.scan(/(^|[^\\])[:\*]([a-zA-Z0-9_]+)/).map{|p| p.last.to_sym}
end
def matching_path(params, other_hash = nil)
@@ -168,6 +170,7 @@ def to_s
private
def raw_paths
+ return [] if @original_path.nil?
@raw_paths ||= begin
start_index, end_index = 0, 1
@raw_paths, chars = [""], @original_path.split('')
@@ -233,15 +236,19 @@ def add_complex_part(node, parts, param_names)
def add_path_to_tree
raise DoubleCompileError if compiled?
@paths ||= begin
- raw_paths.map do |path|
- param_names = []
- node = @router.root
- path.split(/\//).each do |part|
- next if part == ''
- parts = part.scan(/\\.|[:*][a-z0-9_]+|[^:*\\]+/)
- node = parts.size == 1 ? add_normal_part(node, part, param_names) : add_complex_part(node, parts, param_names)
+ if raw_paths.empty?
+ add_non_path_to_tree(@router.root, nil, [])
+ else
+ raw_paths.map do |path|
+ param_names = []
+ node = @router.root
+ path.split(/\//).each do |part|
+ next if part == ''
+ parts = part.scan(/\\.|[:*][a-z0-9_]+|[^:*\\]+/)
+ node = parts.size == 1 ? add_normal_part(node, part, param_names) : add_complex_part(node, parts, param_names)
+ end
+ add_non_path_to_tree(node, path, param_names)
end
- add_non_path_to_tree(node, path, param_names)
end
end
end
@@ -52,7 +52,6 @@
["route", "/foo", {"test": "foo"}]
["route", "/foo.bar", {"format": "bar", "test": "foo"}]
-
[{"route": {"path": "/:test(.:format)", "format": {"regex": "[^\\.]+"}}}]
["route", "/asd@asd.com.json", {"test": "asd@asd.com", "format": "json"}]
View
@@ -73,6 +73,15 @@ def test_passing
assert_body 'working', router.call(Rack::MockRequest.env_for('/'))
end
+ def test_non_path_matching
+ passed, working = router {
+ add(:conditions => {:user_agent => /MSIE/}).to { |env| [200, {}, ['IE']] }
+ add('/').to { |env| [200, {}, ['SOMETHING ELSE']] }
+ }
+ assert_body 'SOMETHING ELSE', router.call(Rack::MockRequest.env_for('/'))
+ assert_body 'IE', router.call(Rack::MockRequest.env_for('/', 'HTTP_USER_AGENT' => 'THIS IS MSIE DAWG'))
+ end
+
def test_passing_with_cascade
passed, working = router {
add('/').to { |env| [200, {'X-Cascade' => 'pass'}, ['pass']] }

0 comments on commit a26d0db

Please sign in to comment.