diff --git a/lib/http_router.rb b/lib/http_router.rb index f5c02da..bebffcc 100644 --- a/lib/http_router.rb +++ b/lib/http_router.rb @@ -57,8 +57,7 @@ def add(path, options = nil) route.trailing_slash_ignore = trailing_slash_ignore route.partially_match = partially_match paths.each_with_index do |path, i| - current_node = @root - path.parts.each { |part| current_node = current_node.add(part) } + current_node = @root.add_path(path) working_set = current_node.add_request_methods(options) working_set.each do |current_node| current_node.value = path diff --git a/lib/http_router/node.rb b/lib/http_router/node.rb index 7fb81c6..ac96f44 100644 --- a/lib/http_router/node.rb +++ b/lib/http_router/node.rb @@ -1,7 +1,7 @@ class HttpRouter class Node - attr_accessor :value, :variable, :catchall, :request_node - attr_reader :linear, :lookup + attr_accessor :value, :variable, :catchall + attr_reader :linear, :lookup, :request_node, :extension_node def initialize reset! @@ -32,6 +32,11 @@ def add(val) end end + def add_extension(ext) + @extension_node ||= Node.new + @extension_node.add(ext) + end + def add_request_methods(options) if options && options[:conditions] current_nodes = [@request_node ||= RequestNode.new] diff --git a/lib/http_router/path.rb b/lib/http_router/path.rb index 88152bd..91b4b4d 100644 --- a/lib/http_router/path.rb +++ b/lib/http_router/path.rb @@ -16,23 +16,25 @@ def url(args, options) path = raw_url(args, options) raise TooManyParametersException.new unless args.empty? Rack::Utils.uri_escape!(path) - generate_querystring(path, options) if options && !options.empty? + generate_querystring(path, options) path end def generate_querystring(uri, params) - uri_size = uri.size - params.each do |k,v| - case v - when Array - v.each do |v_part| - uri << '&' << Rack::Utils.escape(k.to_s) << '%5B%5D=' << Rack::Utils.escape(v_part.to_s) + if params && !params.empty? + uri_size = uri.size + params.each do |k,v| + case v + when Array + v.each do |v_part| + uri << '&' << Rack::Utils.escape(k.to_s) << '%5B%5D=' << Rack::Utils.escape(v_part.to_s) + end + else + uri << '&' << Rack::Utils.escape(k.to_s) << '=' << Rack::Utils.escape(v.to_s) end - else - uri << '&' << Rack::Utils.escape(k.to_s) << '=' << Rack::Utils.escape(v.to_s) end + uri[uri_size] = ?? end - uri[uri_size] = ?? end def variables diff --git a/lib/http_router/root.rb b/lib/http_router/root.rb index 71dbb4f..e7362ce 100644 --- a/lib/http_router/root.rb +++ b/lib/http_router/root.rb @@ -5,6 +5,14 @@ def initialize(base) reset! end + def add_path(path) + node = path.parts.inject(self) { |node, part| node.add(part) } + if path.extension + node = node.add_extension(path.extension) + end + node + end + def find(request) path = request.path_info.dup path.slice!(-1) if @base.ignore_trailing_slash? && path[-1] == ?/ @@ -12,10 +20,13 @@ def find(request) extension = $1 parts = @base.split(path) parts << '' if path[path.size - 1] == ?/ - current_node = self params = [] while current_node + if current_node.extension_node && extension && parts.empty? + parts << extension + current_node = current_node.extension_node + end break if current_node.nil? || (current_node.value && current_node.value.route.partially_match?) || parts.empty? unless current_node.linear.empty? whole_path = parts.join('/') diff --git a/spec/recognize_spec.rb b/spec/recognize_spec.rb index 2f79a11..5e8841e 100644 --- a/spec/recognize_spec.rb +++ b/spec/recognize_spec.rb @@ -97,6 +97,7 @@ response.route.should == route response.extension.should == 'html' response.params_as_hash[:format].should == 'html' + @router.recognize(Rack::MockRequest.env_for('/test')).should be_nil end it "should recognize '/test(.:format)'" do