http_router 0.1.0 → 0.1.1
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 +1 -1
 - data/VERSION +1 -1
 - data/lib/ext/rack/rack_mapper.rb +57 -0
 - data/lib/ext/rack/uri_escape.rb +26 -0
 - data/lib/http_router/glob.rb +2 -1
 - data/lib/http_router/{sinatra.rb → interface/sinatra.rb} +7 -7
 - data/lib/http_router/node.rb +109 -59
 - data/lib/http_router/path.rb +23 -2
 - data/lib/http_router/response.rb +36 -15
 - data/lib/http_router/root.rb +12 -63
 - data/lib/http_router/route.rb +74 -24
 - data/lib/http_router/variable.rb +16 -9
 - data/lib/http_router.rb +55 -31
 - data/spec/generate_spec.rb +81 -12
 - data/spec/misc_spec.rb +38 -0
 - data/spec/rack/dispatch_spec.rb +2 -2
 - data/spec/rack/generate_spec.rb +1 -1
 - data/spec/recognize_spec.rb +25 -2
 - data/spec/sinatra/recognize_spec.rb +2 -2
 - metadata +14 -6
 - data/lib/rack/uri_escape.rb +0 -38
 
    
        data/Rakefile
    CHANGED
    
    | 
         @@ -10,7 +10,7 @@ begin 
     | 
|
| 
       10 
10 
     | 
    
         
             
              end
         
     | 
| 
       11 
11 
     | 
    
         
             
              Jeweler::GemcutterTasks.new
         
     | 
| 
       12 
12 
     | 
    
         
             
            rescue LoadError
         
     | 
| 
       13 
     | 
    
         
            -
              puts "Jeweler not available. Install it with:  
     | 
| 
      
 13 
     | 
    
         
            +
              puts "Jeweler not available. Install it with: gem install jeweler"
         
     | 
| 
       14 
14 
     | 
    
         
             
            end
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
16 
     | 
    
         
             
            require 'spec'
         
     | 
    
        data/VERSION
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            0.1. 
     | 
| 
      
 1 
     | 
    
         
            +
            0.1.1
         
     | 
| 
         @@ -0,0 +1,57 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Replacement for {Rack::Builder} which using HttpRouter to map requests instead of a simple Hash.
         
     | 
| 
      
 2 
     | 
    
         
            +
            # As well, add convenience methods for the request methods.
         
     | 
| 
      
 3 
     | 
    
         
            +
            class Rack::Builder
         
     | 
| 
      
 4 
     | 
    
         
            +
              def initialize(&block)
         
     | 
| 
      
 5 
     | 
    
         
            +
                @router = HttpRouter.new
         
     | 
| 
      
 6 
     | 
    
         
            +
                super
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
              
         
     | 
| 
      
 9 
     | 
    
         
            +
              # Maps a path to a block.
         
     | 
| 
      
 10 
     | 
    
         
            +
              # @param path [String] Path to map to.
         
     | 
| 
      
 11 
     | 
    
         
            +
              # @param options [Hash] Options for added path.
         
     | 
| 
      
 12 
     | 
    
         
            +
              # @see HttpRouter#add
         
     | 
| 
      
 13 
     | 
    
         
            +
              def map(path, options = nil, &block)
         
     | 
| 
      
 14 
     | 
    
         
            +
                @router.add(path).with_options(options).to(&block)
         
     | 
| 
      
 15 
     | 
    
         
            +
                @ins << @router unless @ins.last == @router
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              # Maps a path with request methods `HEAD` and `GET` to a block.
         
     | 
| 
      
 19 
     | 
    
         
            +
              # @param path [String] Path to map to.
         
     | 
| 
      
 20 
     | 
    
         
            +
              # @param options [Hash] Options for added path.
         
     | 
| 
      
 21 
     | 
    
         
            +
              # @see HttpRouter#add
         
     | 
| 
      
 22 
     | 
    
         
            +
              def get(path, options = nil, &block)
         
     | 
| 
      
 23 
     | 
    
         
            +
                @router.get(path).with_options(options).to(&block)
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              # Maps a path with request methods `POST` to a block.
         
     | 
| 
      
 27 
     | 
    
         
            +
              # @param path [String] Path to map to.
         
     | 
| 
      
 28 
     | 
    
         
            +
              # @param options [Hash] Options for added path.
         
     | 
| 
      
 29 
     | 
    
         
            +
              # @see HttpRouter#add
         
     | 
| 
      
 30 
     | 
    
         
            +
              def post(path, options = nil, &block)
         
     | 
| 
      
 31 
     | 
    
         
            +
                @router.post(path).with_options(options).to(&block)
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              # Maps a path with request methods `PUT` to a block.
         
     | 
| 
      
 35 
     | 
    
         
            +
              # @param path [String] Path to map to.
         
     | 
| 
      
 36 
     | 
    
         
            +
              # @param options [Hash] Options for added path.
         
     | 
| 
      
 37 
     | 
    
         
            +
              # @see HttpRouter#add
         
     | 
| 
      
 38 
     | 
    
         
            +
              def put(path, options = nil, &block)
         
     | 
| 
      
 39 
     | 
    
         
            +
                @router.put(path).with_options(options).to(&block)
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              # Maps a path with request methods `DELETE` to a block.
         
     | 
| 
      
 43 
     | 
    
         
            +
              # @param path [String] Path to map to.
         
     | 
| 
      
 44 
     | 
    
         
            +
              # @param options [Hash] Options for added path.
         
     | 
| 
      
 45 
     | 
    
         
            +
              # @see HttpRouter#add
         
     | 
| 
      
 46 
     | 
    
         
            +
              def delete(path, options = nil, &block)
         
     | 
| 
      
 47 
     | 
    
         
            +
                @router.delete(path).with_options(options).to(&block)
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              # Maps a path with request methods `HEAD` to a block.
         
     | 
| 
      
 51 
     | 
    
         
            +
              # @param path [String] Path to map to.
         
     | 
| 
      
 52 
     | 
    
         
            +
              # @param options [Hash] Options for added path.
         
     | 
| 
      
 53 
     | 
    
         
            +
              # @see HttpRouter#add
         
     | 
| 
      
 54 
     | 
    
         
            +
              def head(path, options = nil, &block)
         
     | 
| 
      
 55 
     | 
    
         
            +
                @router.head(path).with_options(options).to(&block)
         
     | 
| 
      
 56 
     | 
    
         
            +
              end
         
     | 
| 
      
 57 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rack::Utils
         
     | 
| 
      
 2 
     | 
    
         
            +
              def uri_escape(s)
         
     | 
| 
      
 3 
     | 
    
         
            +
                s.to_s.gsub(/([^:\/?\[\]\-_~\.!\$&'\(\)\*\+,;=@a-zA-Z0-9]+)/n) {
         
     | 
| 
      
 4 
     | 
    
         
            +
                  '%'<<$1.unpack('H2'*$1.size).join('%').upcase
         
     | 
| 
      
 5 
     | 
    
         
            +
                }
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
      
 7 
     | 
    
         
            +
              module_function :uri_escape
         
     | 
| 
      
 8 
     | 
    
         
            +
            end unless Rack::Utils.respond_to?(:uri_escape)
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            module Rack::Utils
         
     | 
| 
      
 11 
     | 
    
         
            +
              def uri_escape!(s)
         
     | 
| 
      
 12 
     | 
    
         
            +
                s.to_s.gsub!(/([^:\/?\[\]\-_~\.!\$&'\(\)\*\+,;=@a-zA-Z0-9]+)/n) {
         
     | 
| 
      
 13 
     | 
    
         
            +
                  '%'<<$1.unpack('H2'*$1.size).join('%').upcase
         
     | 
| 
      
 14 
     | 
    
         
            +
                }
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
              module_function :uri_escape!
         
     | 
| 
      
 17 
     | 
    
         
            +
            end unless Rack::Utils.respond_to?(:uri_escape!)
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            module Rack::Utils
         
     | 
| 
      
 20 
     | 
    
         
            +
              def uri_unescape(s)
         
     | 
| 
      
 21 
     | 
    
         
            +
                gsub(/((?:%[0-9a-fA-F]{2})+)/n){
         
     | 
| 
      
 22 
     | 
    
         
            +
                  [$1.delete('%')].pack('H*')
         
     | 
| 
      
 23 
     | 
    
         
            +
                }
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
              module_function :uri_unescape
         
     | 
| 
      
 26 
     | 
    
         
            +
            end unless Rack::Utils.respond_to?(:uri_unescape)
         
     | 
    
        data/lib/http_router/glob.rb
    CHANGED
    
    | 
         @@ -1,11 +1,12 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            class HttpRouter
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Glob < Variable
         
     | 
| 
       3 
     | 
    
         
            -
                def matches(parts, whole_path)
         
     | 
| 
      
 3 
     | 
    
         
            +
                def matches(env, parts, whole_path)
         
     | 
| 
       4 
4 
     | 
    
         
             
                  if @matches_with && match = @matches_with.match(parts.first)
         
     | 
| 
       5 
5 
     | 
    
         
             
                    params = [parts.shift]
         
     | 
| 
       6 
6 
     | 
    
         
             
                    while !parts.empty? and match = @matches_with.match(parts.first)
         
     | 
| 
       7 
7 
     | 
    
         
             
                      params << parts.shift
         
     | 
| 
       8 
8 
     | 
    
         
             
                    end
         
     | 
| 
      
 9 
     | 
    
         
            +
                    return unless additional_matchers(env, params)
         
     | 
| 
       9 
10 
     | 
    
         
             
                    whole_path.replace(parts.join('/'))
         
     | 
| 
       10 
11 
     | 
    
         
             
                    params
         
     | 
| 
       11 
12 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -1,4 +1,4 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            $LOAD_PATH << File.join(File.dirname(__FILE__), '..')
         
     | 
| 
      
 1 
     | 
    
         
            +
            $LOAD_PATH << File.join(File.dirname(__FILE__), '..', '..')
         
     | 
| 
       2 
2 
     | 
    
         
             
            require 'http_router'
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            class HttpRouter
         
     | 
| 
         @@ -26,17 +26,17 @@ class HttpRouter 
     | 
|
| 
       26 
26 
     | 
    
         
             
                    private
         
     | 
| 
       27 
27 
     | 
    
         
             
                      def route!(base=self.class, pass_block=nil)
         
     | 
| 
       28 
28 
     | 
    
         
             
                        if base.router and match = base.router.recognize(@request)
         
     | 
| 
       29 
     | 
    
         
            -
                          if match. 
     | 
| 
       30 
     | 
    
         
            -
                            route_eval { 
         
     | 
| 
       31 
     | 
    
         
            -
                              match.headers.each{|k,v| response[k] = v}
         
     | 
| 
       32 
     | 
    
         
            -
                              status match.status
         
     | 
| 
       33 
     | 
    
         
            -
                            }
         
     | 
| 
       34 
     | 
    
         
            -
                          else
         
     | 
| 
      
 29 
     | 
    
         
            +
                          if match.matched?
         
     | 
| 
       35 
30 
     | 
    
         
             
                            @block_params = match.params
         
     | 
| 
       36 
31 
     | 
    
         
             
                            (@params ||= {}).merge!(match.params_as_hash)
         
     | 
| 
       37 
32 
     | 
    
         
             
                            pass_block = catch(:pass) do
         
     | 
| 
       38 
33 
     | 
    
         
             
                              route_eval(&match.route.dest)
         
     | 
| 
       39 
34 
     | 
    
         
             
                            end
         
     | 
| 
      
 35 
     | 
    
         
            +
                          else
         
     | 
| 
      
 36 
     | 
    
         
            +
                            route_eval { 
         
     | 
| 
      
 37 
     | 
    
         
            +
                              match.headers.each{|k,v| response[k] = v}
         
     | 
| 
      
 38 
     | 
    
         
            +
                              status match.status
         
     | 
| 
      
 39 
     | 
    
         
            +
                            }
         
     | 
| 
       40 
40 
     | 
    
         
             
                          end
         
     | 
| 
       41 
41 
     | 
    
         
             
                        end
         
     | 
| 
       42 
42 
     | 
    
         | 
    
        data/lib/http_router/node.rb
    CHANGED
    
    | 
         @@ -3,37 +3,41 @@ class HttpRouter 
     | 
|
| 
       3 
3 
     | 
    
         
             
                attr_accessor :value, :variable, :catchall
         
     | 
| 
       4 
4 
     | 
    
         
             
                attr_reader :linear, :lookup, :request_node, :extension_node
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
                def initialize
         
     | 
| 
      
 6 
     | 
    
         
            +
                def initialize(base)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @router = base
         
     | 
| 
       7 
8 
     | 
    
         
             
                  reset!
         
     | 
| 
       8 
9 
     | 
    
         
             
                end
         
     | 
| 
       9 
10 
     | 
    
         | 
| 
       10 
11 
     | 
    
         
             
                def reset!
         
     | 
| 
       11 
     | 
    
         
            -
                  @linear =  
     | 
| 
       12 
     | 
    
         
            -
                  @lookup =  
     | 
| 
      
 12 
     | 
    
         
            +
                  @linear = nil
         
     | 
| 
      
 13 
     | 
    
         
            +
                  @lookup = nil
         
     | 
| 
       13 
14 
     | 
    
         
             
                  @catchall = nil
         
     | 
| 
       14 
15 
     | 
    
         
             
                end
         
     | 
| 
       15 
16 
     | 
    
         | 
| 
       16 
17 
     | 
    
         
             
                def add(val)
         
     | 
| 
       17 
18 
     | 
    
         
             
                  if val.is_a?(Variable)
         
     | 
| 
       18 
19 
     | 
    
         
             
                    if val.matches_with
         
     | 
| 
       19 
     | 
    
         
            -
                      new_node =  
     | 
| 
      
 20 
     | 
    
         
            +
                      new_node = router.node
         
     | 
| 
      
 21 
     | 
    
         
            +
                      create_linear
         
     | 
| 
       20 
22 
     | 
    
         
             
                      @linear << [val, new_node]
         
     | 
| 
       21 
23 
     | 
    
         
             
                      new_node
         
     | 
| 
       22 
24 
     | 
    
         
             
                    else
         
     | 
| 
       23 
     | 
    
         
            -
                      @catchall ||=  
     | 
| 
      
 25 
     | 
    
         
            +
                      @catchall ||= router.node
         
     | 
| 
       24 
26 
     | 
    
         
             
                      @catchall.variable = val
         
     | 
| 
       25 
27 
     | 
    
         
             
                      @catchall
         
     | 
| 
       26 
28 
     | 
    
         
             
                    end
         
     | 
| 
       27 
29 
     | 
    
         
             
                  elsif val.is_a?(Regexp)
         
     | 
| 
       28 
     | 
    
         
            -
                     
     | 
| 
      
 30 
     | 
    
         
            +
                    create_linear
         
     | 
| 
      
 31 
     | 
    
         
            +
                    @linear << [val, router.node]
         
     | 
| 
       29 
32 
     | 
    
         
             
                    @linear.last.last
         
     | 
| 
       30 
33 
     | 
    
         
             
                  else
         
     | 
| 
       31 
     | 
    
         
            -
                     
     | 
| 
      
 34 
     | 
    
         
            +
                    create_lookup
         
     | 
| 
      
 35 
     | 
    
         
            +
                    @lookup[val] ||= router.node
         
     | 
| 
       32 
36 
     | 
    
         
             
                  end
         
     | 
| 
       33 
37 
     | 
    
         
             
                end
         
     | 
| 
       34 
38 
     | 
    
         | 
| 
       35 
39 
     | 
    
         
             
                def add_extension(ext)
         
     | 
| 
       36 
     | 
    
         
            -
                  @extension_node ||=  
     | 
| 
      
 40 
     | 
    
         
            +
                  @extension_node ||= router.node
         
     | 
| 
       37 
41 
     | 
    
         
             
                  @extension_node.add(ext)
         
     | 
| 
       38 
42 
     | 
    
         
             
                end
         
     | 
| 
       39 
43 
     | 
    
         | 
| 
         @@ -43,7 +47,7 @@ class HttpRouter 
     | 
|
| 
       43 
47 
     | 
    
         
             
                  elsif @request_node
         
     | 
| 
       44 
48 
     | 
    
         
             
                    current_node = @request_node
         
     | 
| 
       45 
49 
     | 
    
         
             
                    while current_node.request_method
         
     | 
| 
       46 
     | 
    
         
            -
                      current_node = (current_node.catchall ||=  
     | 
| 
      
 50 
     | 
    
         
            +
                      current_node = (current_node.catchall ||= router.request_node)
         
     | 
| 
       47 
51 
     | 
    
         
             
                    end
         
     | 
| 
       48 
52 
     | 
    
         
             
                    [current_node]
         
     | 
| 
       49 
53 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -52,12 +56,14 @@ class HttpRouter 
     | 
|
| 
       52 
56 
     | 
    
         
             
                end
         
     | 
| 
       53 
57 
     | 
    
         | 
| 
       54 
58 
     | 
    
         
             
                protected
         
     | 
| 
      
 59 
     | 
    
         
            +
                
         
     | 
| 
      
 60 
     | 
    
         
            +
                attr_reader :router
         
     | 
| 
       55 
61 
     | 
    
         | 
| 
       56 
62 
     | 
    
         
             
                def transplant_value
         
     | 
| 
       57 
63 
     | 
    
         
             
                  if @value
         
     | 
| 
       58 
64 
     | 
    
         
             
                    target_node = @request_node
         
     | 
| 
       59 
65 
     | 
    
         
             
                    while target_node.request_method
         
     | 
| 
       60 
     | 
    
         
            -
                      target_node = (target_node.catchall ||=  
     | 
| 
      
 66 
     | 
    
         
            +
                      target_node = (target_node.catchall ||= router.request_node)
         
     | 
| 
       61 
67 
     | 
    
         
             
                    end
         
     | 
| 
       62 
68 
     | 
    
         
             
                    target_node.value = @value
         
     | 
| 
       63 
69 
     | 
    
         
             
                    @value = nil
         
     | 
| 
         @@ -65,89 +71,133 @@ class HttpRouter 
     | 
|
| 
       65 
71 
     | 
    
         
             
                end
         
     | 
| 
       66 
72 
     | 
    
         | 
| 
       67 
73 
     | 
    
         
             
                def generate_request_method_tree(request_options)
         
     | 
| 
       68 
     | 
    
         
            -
                  raise if (request_options.keys & RequestNode::RequestMethods).size != request_options.size
         
     | 
| 
       69 
     | 
    
         
            -
                  
         
     | 
| 
       70 
     | 
    
         
            -
                  
         
     | 
| 
       71 
     | 
    
         
            -
                  current_nodes = [@request_node ||= RequestNode.new]
         
     | 
| 
      
 74 
     | 
    
         
            +
                  raise(UnsupportedRequestConditionError.new) if (request_options.keys & RequestNode::RequestMethods).size != request_options.size
         
     | 
| 
      
 75 
     | 
    
         
            +
                  current_nodes = [self]
         
     | 
| 
       72 
76 
     | 
    
         
             
                  RequestNode::RequestMethods.each do |method|
         
     | 
| 
       73 
     | 
    
         
            -
                     
     | 
| 
       74 
     | 
    
         
            -
                      if  
     | 
| 
       75 
     | 
    
         
            -
                         
     | 
| 
      
 77 
     | 
    
         
            +
                    if request_options.key?(method) # so, the request method we care about it ..
         
     | 
| 
      
 78 
     | 
    
         
            +
                      if current_nodes == [self]
         
     | 
| 
      
 79 
     | 
    
         
            +
                        current_nodes = [@request_node ||= router.request_node]
         
     | 
| 
      
 80 
     | 
    
         
            +
                      end
         
     | 
| 
      
 81 
     | 
    
         
            +
                      
         
     | 
| 
      
 82 
     | 
    
         
            +
                      for current_node_index in (0...current_nodes.size)
         
     | 
| 
      
 83 
     | 
    
         
            +
                        current_node = current_nodes.at(current_node_index)
         
     | 
| 
      
 84 
     | 
    
         
            +
                        if request_options.key?(method)  #we care about the method
         
     | 
| 
       76 
85 
     | 
    
         
             
                          unless current_node.request_method
         
     | 
| 
       77 
86 
     | 
    
         
             
                            current_node.request_method = method
         
     | 
| 
       78 
87 
     | 
    
         
             
                          end
         
     | 
| 
       79 
     | 
    
         
            -
                        
         
     | 
| 
       80 
88 
     | 
    
         
             
                          case RequestNode::RequestMethods.index(method) <=> RequestNode::RequestMethods.index(current_node.request_method)
         
     | 
| 
       81 
89 
     | 
    
         
             
                          when 0 #use this node
         
     | 
| 
       82 
90 
     | 
    
         
             
                            if request_options[method].is_a?(Regexp)
         
     | 
| 
       83 
     | 
    
         
            -
                               
     | 
| 
       84 
     | 
    
         
            -
                               
     | 
| 
      
 91 
     | 
    
         
            +
                              new_node = router.request_node
         
     | 
| 
      
 92 
     | 
    
         
            +
                              current_nodes[current_node_index] = new_node
         
     | 
| 
      
 93 
     | 
    
         
            +
                              current_node.create_linear
         
     | 
| 
      
 94 
     | 
    
         
            +
                              current_node.linear << [request_options[method], new_node]
         
     | 
| 
       85 
95 
     | 
    
         
             
                            elsif request_options[method].is_a?(Array)
         
     | 
| 
       86 
     | 
    
         
            -
                               
     | 
| 
      
 96 
     | 
    
         
            +
                              current_node.create_lookup
         
     | 
| 
      
 97 
     | 
    
         
            +
                              current_nodes[current_node_index] = request_options[method].map{|val| current_node.lookup[val] ||= router.request_node}
         
     | 
| 
       87 
98 
     | 
    
         
             
                            else
         
     | 
| 
       88 
     | 
    
         
            -
                               
     | 
| 
      
 99 
     | 
    
         
            +
                              current_node.create_lookup
         
     | 
| 
      
 100 
     | 
    
         
            +
                              current_nodes[current_node_index] = (current_node.lookup[request_options[method]] ||= router.request_node)
         
     | 
| 
       89 
101 
     | 
    
         
             
                            end
         
     | 
| 
       90 
102 
     | 
    
         
             
                          when 1 #this node is farther ahead
         
     | 
| 
       91 
     | 
    
         
            -
                            current_nodes[current_node_index] = (current_node.catchall ||=  
     | 
| 
       92 
     | 
    
         
            -
                            redo
         
     | 
| 
      
 103 
     | 
    
         
            +
                            current_nodes[current_node_index] = (current_node.catchall ||= router.request_node)
         
     | 
| 
       93 
104 
     | 
    
         
             
                          when -1 #this method is more important than the current node
         
     | 
| 
       94 
     | 
    
         
            -
                             
     | 
| 
       95 
     | 
    
         
            -
                             
     | 
| 
       96 
     | 
    
         
            -
                             
     | 
| 
       97 
     | 
    
         
            -
                            current_nodes[current_node_index] = new_node
         
     | 
| 
      
 105 
     | 
    
         
            +
                            next_node = current_node.dup
         
     | 
| 
      
 106 
     | 
    
         
            +
                            current_node.reset!
         
     | 
| 
      
 107 
     | 
    
         
            +
                            current_node.request_method = method
         
     | 
| 
       98 
108 
     | 
    
         
             
                            redo
         
     | 
| 
       99 
109 
     | 
    
         
             
                          end
         
     | 
| 
       100 
110 
     | 
    
         
             
                        else
         
     | 
| 
       101 
     | 
    
         
            -
                           
     | 
| 
       102 
     | 
    
         
            -
                          redo
         
     | 
| 
      
 111 
     | 
    
         
            +
                          current_node.catchall ||= router.request_node
         
     | 
| 
       103 
112 
     | 
    
         
             
                        end
         
     | 
| 
       104 
     | 
    
         
            -
                      elsif !current_node
         
     | 
| 
       105 
     | 
    
         
            -
                        @request_node = RequestNode.new
         
     | 
| 
       106 
     | 
    
         
            -
                        current_nodes[current_node_index] = @request_node
         
     | 
| 
       107 
     | 
    
         
            -
                        redo
         
     | 
| 
       108 
     | 
    
         
            -
                      else
         
     | 
| 
       109 
     | 
    
         
            -
                        current_node.catchall ||= RequestNode.new
         
     | 
| 
       110 
113 
     | 
    
         
             
                      end
         
     | 
| 
      
 114 
     | 
    
         
            +
                      current_nodes.flatten!
         
     | 
| 
      
 115 
     | 
    
         
            +
                    elsif current_nodes.first.is_a?(RequestNode) && !current_nodes.first.request_method.nil?
         
     | 
| 
      
 116 
     | 
    
         
            +
                      current_nodes.map!{|n| n.catchall ||= router.request_node}
         
     | 
| 
       111 
117 
     | 
    
         
             
                    end
         
     | 
| 
       112 
     | 
    
         
            -
                    current_nodes.flatten!
         
     | 
| 
       113 
118 
     | 
    
         
             
                  end
         
     | 
| 
       114 
119 
     | 
    
         
             
                  transplant_value
         
     | 
| 
       115 
120 
     | 
    
         
             
                  current_nodes
         
     | 
| 
       116 
121 
     | 
    
         
             
                end
         
     | 
| 
       117 
122 
     | 
    
         | 
| 
       118 
     | 
    
         
            -
                def  
     | 
| 
       119 
     | 
    
         
            -
                   
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
                     
     | 
| 
       122 
     | 
    
         
            -
             
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
                       
     | 
| 
       125 
     | 
    
         
            -
                       
     | 
| 
       126 
     | 
    
         
            -
             
     | 
| 
       127 
     | 
    
         
            -
             
     | 
| 
       128 
     | 
    
         
            -
                           
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
                         
     | 
| 
       131 
     | 
    
         
            -
                           
     | 
| 
       132 
     | 
    
         
            -
                           
     | 
| 
      
 123 
     | 
    
         
            +
                def find_on_parts(request, parts, extension, params)
         
     | 
| 
      
 124 
     | 
    
         
            +
                  if parts.empty? && extension_node && extension
         
     | 
| 
      
 125 
     | 
    
         
            +
                    parts << extension
         
     | 
| 
      
 126 
     | 
    
         
            +
                    extension_node.find_on_parts(request, parts, extension, params)
         
     | 
| 
      
 127 
     | 
    
         
            +
                  else
         
     | 
| 
      
 128 
     | 
    
         
            +
                    if @linear && !@linear.empty?
         
     | 
| 
      
 129 
     | 
    
         
            +
                      whole_path = parts.join('/')
         
     | 
| 
      
 130 
     | 
    
         
            +
                      next_node = @linear.find do |(tester, node)|
         
     | 
| 
      
 131 
     | 
    
         
            +
                        if tester.is_a?(Regexp) and match = whole_path.match(tester) #and match.index == 0 TODO
         
     | 
| 
      
 132 
     | 
    
         
            +
                          whole_path.slice!(0,match[0].size)
         
     | 
| 
      
 133 
     | 
    
         
            +
                          parts.replace(router.split(whole_path))
         
     | 
| 
      
 134 
     | 
    
         
            +
                          node
         
     | 
| 
      
 135 
     | 
    
         
            +
                        elsif new_params = tester.matches(request.env, parts, whole_path)
         
     | 
| 
      
 136 
     | 
    
         
            +
                          params << new_params
         
     | 
| 
      
 137 
     | 
    
         
            +
                          node
         
     | 
| 
      
 138 
     | 
    
         
            +
                        else
         
     | 
| 
      
 139 
     | 
    
         
            +
                          nil
         
     | 
| 
       133 
140 
     | 
    
         
             
                        end
         
     | 
| 
       134 
141 
     | 
    
         
             
                      end
         
     | 
| 
       135 
     | 
    
         
            -
                       
     | 
| 
       136 
     | 
    
         
            -
             
     | 
| 
       137 
     | 
    
         
            -
             
     | 
| 
       138 
     | 
    
         
            -
                       
     | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
       140 
     | 
    
         
            -
             
     | 
| 
      
 142 
     | 
    
         
            +
                      return next_node.last.find_on_parts(request, parts, extension, params) if next_node
         
     | 
| 
      
 143 
     | 
    
         
            +
                    end
         
     | 
| 
      
 144 
     | 
    
         
            +
                    if match = @lookup && @lookup[parts.first]
         
     | 
| 
      
 145 
     | 
    
         
            +
                      parts.shift
         
     | 
| 
      
 146 
     | 
    
         
            +
                      match.find_on_parts(request, parts, extension, params)
         
     | 
| 
      
 147 
     | 
    
         
            +
                    elsif @catchall
         
     | 
| 
      
 148 
     | 
    
         
            +
                      params << @catchall.variable.matches(request.env, parts, whole_path)
         
     | 
| 
      
 149 
     | 
    
         
            +
                      parts.shift
         
     | 
| 
      
 150 
     | 
    
         
            +
                      @catchall.find_on_parts(request, parts, extension, params)
         
     | 
| 
      
 151 
     | 
    
         
            +
                    elsif parts.size == 1 && parts.first == '' && (value && value.route.trailing_slash_ignore?)
         
     | 
| 
      
 152 
     | 
    
         
            +
                      parts.shift
         
     | 
| 
      
 153 
     | 
    
         
            +
                      find_on_parts(request, parts, extension, params)
         
     | 
| 
      
 154 
     | 
    
         
            +
                    elsif request_node
         
     | 
| 
      
 155 
     | 
    
         
            +
                      request_node.find_on_request_methods(request)
         
     | 
| 
      
 156 
     | 
    
         
            +
                    elsif @value
         
     | 
| 
      
 157 
     | 
    
         
            +
                      self
         
     | 
| 
      
 158 
     | 
    
         
            +
                    else
         
     | 
| 
      
 159 
     | 
    
         
            +
                      nil
         
     | 
| 
       141 
160 
     | 
    
         
             
                    end
         
     | 
| 
       142 
161 
     | 
    
         
             
                  end
         
     | 
| 
       143 
     | 
    
         
            -
                  current_node
         
     | 
| 
       144 
162 
     | 
    
         
             
                end
         
     | 
| 
       145 
163 
     | 
    
         | 
| 
      
 164 
     | 
    
         
            +
                def create_linear
         
     | 
| 
      
 165 
     | 
    
         
            +
                  @linear ||= []
         
     | 
| 
      
 166 
     | 
    
         
            +
                end
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                def create_lookup
         
     | 
| 
      
 169 
     | 
    
         
            +
                  @lookup ||= {}
         
     | 
| 
      
 170 
     | 
    
         
            +
                end
         
     | 
| 
       146 
171 
     | 
    
         
             
              end
         
     | 
| 
       147 
172 
     | 
    
         | 
| 
       148 
173 
     | 
    
         
             
              class RequestNode < Node
         
     | 
| 
       149 
174 
     | 
    
         
             
                RequestMethods =  [:request_method, :host, :port, :scheme]
         
     | 
| 
       150 
175 
     | 
    
         
             
                attr_accessor :request_method
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
                def find_on_request_methods(request)
         
     | 
| 
      
 178 
     | 
    
         
            +
                  if @request_method
         
     | 
| 
      
 179 
     | 
    
         
            +
                    request_value = request.send(request_method)
         
     | 
| 
      
 180 
     | 
    
         
            +
                    if @linear && !@linear.empty?
         
     | 
| 
      
 181 
     | 
    
         
            +
                      next_node = @linear.find do |(regexp, node)|
         
     | 
| 
      
 182 
     | 
    
         
            +
                        regexp === request_value
         
     | 
| 
      
 183 
     | 
    
         
            +
                      end
         
     | 
| 
      
 184 
     | 
    
         
            +
                      next_node &&= next_node.find_on_request_methods(request)
         
     | 
| 
      
 185 
     | 
    
         
            +
                      return next_node if next_node
         
     | 
| 
      
 186 
     | 
    
         
            +
                    end
         
     | 
| 
      
 187 
     | 
    
         
            +
                    if @lookup and next_node = (@lookup[request_value] && @lookup[request_value].find_on_request_methods(request))
         
     | 
| 
      
 188 
     | 
    
         
            +
                      return next_node
         
     | 
| 
      
 189 
     | 
    
         
            +
                    elsif next_node = (@catchall && @catchall.find_on_request_methods(request))
         
     | 
| 
      
 190 
     | 
    
         
            +
                      return next_node
         
     | 
| 
      
 191 
     | 
    
         
            +
                    end
         
     | 
| 
      
 192 
     | 
    
         
            +
                  end
         
     | 
| 
      
 193 
     | 
    
         
            +
                  
         
     | 
| 
      
 194 
     | 
    
         
            +
                  if @value
         
     | 
| 
      
 195 
     | 
    
         
            +
                    self
         
     | 
| 
      
 196 
     | 
    
         
            +
                  else
         
     | 
| 
      
 197 
     | 
    
         
            +
                    current_node = request_method == :request_method ? Response.unmatched(405, {"Allow" => @lookup.keys.join(", ")}) : nil
         
     | 
| 
      
 198 
     | 
    
         
            +
                  end
         
     | 
| 
      
 199 
     | 
    
         
            +
                end
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
       151 
201 
     | 
    
         
             
              end
         
     | 
| 
       152 
202 
     | 
    
         | 
| 
       153 
203 
     | 
    
         
             
            end
         
     | 
    
        data/lib/http_router/path.rb
    CHANGED
    
    | 
         @@ -5,14 +5,35 @@ class HttpRouter 
     | 
|
| 
       5 
5 
     | 
    
         
             
                attr_accessor :route
         
     | 
| 
       6 
6 
     | 
    
         
             
                def initialize(path, parts, extension)
         
     | 
| 
       7 
7 
     | 
    
         
             
                  @path, @parts, @extension = path, parts, extension
         
     | 
| 
       8 
     | 
    
         
            -
                   
     | 
| 
      
 8 
     | 
    
         
            +
                  if duplicate_variable_names = variable_names.dup.uniq!
         
     | 
| 
      
 9 
     | 
    
         
            +
                    raise AmbiguousVariableException.new("You have duplicate variable name present: #{duplicate_variable_names.join(', ')}")
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  eval_path = path.gsub(/[:\*]([a-zA-Z0-9_]+)/) {"\#{args.shift || (options && options.delete(:#{$1})) || raise(MissingParameterException.new(\"missing parameter #{$1}\"))}" }
         
     | 
| 
       9 
13 
     | 
    
         
             
                  instance_eval "
         
     | 
| 
       10 
14 
     | 
    
         
             
                  def raw_url(args,options)
         
     | 
| 
       11 
     | 
    
         
            -
                    \"#{ 
     | 
| 
      
 15 
     | 
    
         
            +
                    \"#{eval_path}\"
         
     | 
| 
       12 
16 
     | 
    
         
             
                  end
         
     | 
| 
       13 
17 
     | 
    
         
             
                  "
         
     | 
| 
       14 
18 
     | 
    
         
             
                end
         
     | 
| 
       15 
19 
     | 
    
         | 
| 
      
 20 
     | 
    
         
            +
                def ===(other_path)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  return false if @parts.size != other_path.parts.size
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @parts.each_with_index {|p,i| 
         
     | 
| 
      
 23 
     | 
    
         
            +
                    return unless compare_parts(p, other_path.parts[i])
         
     | 
| 
      
 24 
     | 
    
         
            +
                  }
         
     | 
| 
      
 25 
     | 
    
         
            +
                  compare_parts(@extension, other_path.extension)
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                def compare_parts(p1, p2)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  case p1
         
     | 
| 
      
 30 
     | 
    
         
            +
                  when Glob then p2.is_a?(Glob)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  when Variable then p2.is_a?(Variable)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  else
         
     | 
| 
      
 33 
     | 
    
         
            +
                    p1 == p2
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
       16 
37 
     | 
    
         
             
                def url(args, options)
         
     | 
| 
       17 
38 
     | 
    
         
             
                  path = raw_url(args, options)
         
     | 
| 
       18 
39 
     | 
    
         
             
                  raise TooManyParametersException.new unless args.empty?
         
     | 
    
        data/lib/http_router/response.rb
    CHANGED
    
    | 
         @@ -1,25 +1,46 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            class HttpRouter
         
     | 
| 
       2 
     | 
    
         
            -
               
     | 
| 
       3 
     | 
    
         
            -
                 
     | 
| 
      
 2 
     | 
    
         
            +
              module Response
         
     | 
| 
      
 3 
     | 
    
         
            +
                def self.matched(*args)
         
     | 
| 
      
 4 
     | 
    
         
            +
                  Matched.new(*args)
         
     | 
| 
      
 5 
     | 
    
         
            +
                end
         
     | 
| 
       4 
6 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
                def  
     | 
| 
       6 
     | 
    
         
            -
                   
     | 
| 
       7 
     | 
    
         
            -
                  super
         
     | 
| 
       8 
     | 
    
         
            -
                  @params_as_hash = path.variable_names.zip(params).inject({}) {|h, (k,v)| h[k] = v; h }
         
     | 
| 
       9 
     | 
    
         
            -
                  @params_as_hash[path.extension.name] = extension if path.extension && path.extension.is_a?(Variable)
         
     | 
| 
      
 7 
     | 
    
         
            +
                def self.unmatched(*args)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  Unmatched.new(*args)
         
     | 
| 
       10 
9 
     | 
    
         
             
                end
         
     | 
| 
       11 
10 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
                 
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
      
 11 
     | 
    
         
            +
                private
         
     | 
| 
      
 12 
     | 
    
         
            +
                class Unmatched < Struct.new(:status, :headers)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  def matched?
         
     | 
| 
      
 14 
     | 
    
         
            +
                    false
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
       14 
16 
     | 
    
         
             
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                class Matched < Struct.new(:path, :params, :extension, :matched_path, :remaining_path)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  attr_reader :params_as_hash, :route
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def initialize(path, params, extension, matched_path, remaining_path)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    raise if matched_path.nil?
         
     | 
| 
      
 23 
     | 
    
         
            +
                    super
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @params_as_hash = path.variable_names.zip(params).inject({}) {|h, (k,v)| h[k] = v; h }
         
     | 
| 
      
 25 
     | 
    
         
            +
                    @params_as_hash[path.extension.name] = extension if path.extension && path.extension.is_a?(Variable)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  def matched?
         
     | 
| 
      
 29 
     | 
    
         
            +
                    true
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  def route
         
     | 
| 
      
 33 
     | 
    
         
            +
                    path.route
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
       15 
35 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
      
 36 
     | 
    
         
            +
                  def dest
         
     | 
| 
      
 37 
     | 
    
         
            +
                    route.dest
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
                  alias_method :destination, :dest
         
     | 
| 
       20 
40 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
      
 41 
     | 
    
         
            +
                  def partial_match?
         
     | 
| 
      
 42 
     | 
    
         
            +
                    remaining_path
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
       23 
44 
     | 
    
         
             
                end
         
     | 
| 
       24 
45 
     | 
    
         
             
              end
         
     | 
| 
       25 
46 
     | 
    
         
             
            end
         
     | 
    
        data/lib/http_router/root.rb
    CHANGED
    
    | 
         @@ -1,10 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            class HttpRouter
         
     | 
| 
       2 
2 
     | 
    
         
             
              class Root < Node
         
     | 
| 
       3 
     | 
    
         
            -
                def initialize(base)
         
     | 
| 
       4 
     | 
    
         
            -
                  @base = base
         
     | 
| 
       5 
     | 
    
         
            -
                  reset!
         
     | 
| 
       6 
     | 
    
         
            -
                end
         
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
3 
     | 
    
         
             
                def add_path(path)
         
     | 
| 
       9 
4 
     | 
    
         
             
                  node = path.parts.inject(self) { |node, part| node.add(part) }
         
     | 
| 
       10 
5 
     | 
    
         
             
                  if path.extension
         
     | 
| 
         @@ -15,69 +10,23 @@ class HttpRouter 
     | 
|
| 
       15 
10 
     | 
    
         | 
| 
       16 
11 
     | 
    
         
             
                def find(request)
         
     | 
| 
       17 
12 
     | 
    
         
             
                  path = request.path_info.dup
         
     | 
| 
       18 
     | 
    
         
            -
                  path.slice!(-1) if  
     | 
| 
      
 13 
     | 
    
         
            +
                  path.slice!(-1) if router.ignore_trailing_slash? && path[-1] == ?/
         
     | 
| 
       19 
14 
     | 
    
         
             
                  extension = extract_extension(path)
         
     | 
| 
       20 
     | 
    
         
            -
                  parts =  
     | 
| 
      
 15 
     | 
    
         
            +
                  parts = router.split(path)
         
     | 
| 
       21 
16 
     | 
    
         
             
                  parts << '' if path[path.size - 1] == ?/
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
17 
     | 
    
         
             
                  params = []
         
     | 
| 
       24 
     | 
    
         
            -
                   
     | 
| 
       25 
     | 
    
         
            -
                     
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
      
 18 
     | 
    
         
            +
                  process_response(
         
     | 
| 
      
 19 
     | 
    
         
            +
                    find_on_parts(request, parts, extension, params),
         
     | 
| 
      
 20 
     | 
    
         
            +
                    parts,
         
     | 
| 
      
 21 
     | 
    
         
            +
                    extension,
         
     | 
| 
      
 22 
     | 
    
         
            +
                    params, 
         
     | 
| 
      
 23 
     | 
    
         
            +
                    request
         
     | 
| 
      
 24 
     | 
    
         
            +
                  )
         
     | 
| 
       29 
25 
     | 
    
         
             
                end
         
     | 
| 
       30 
26 
     | 
    
         | 
| 
       31 
27 
     | 
    
         
             
                private
         
     | 
| 
       32 
     | 
    
         
            -
                
         
     | 
| 
       33 
     | 
    
         
            -
                def process_parts(parts, extension, params)
         
     | 
| 
       34 
     | 
    
         
            -
                  current_node = self
         
     | 
| 
       35 
     | 
    
         
            -
                  loop do
         
     | 
| 
       36 
     | 
    
         
            -
                    if parts.empty? && current_node.extension_node && extension
         
     | 
| 
       37 
     | 
    
         
            -
                      parts << extension
         
     | 
| 
       38 
     | 
    
         
            -
                      current_node = current_node.extension_node
         
     | 
| 
       39 
     | 
    
         
            -
                    end
         
     | 
| 
       40 
     | 
    
         
            -
                    break if current_node.nil? || (current_node.value && current_node.value.route.partially_match?) || parts.empty?
         
     | 
| 
       41 
     | 
    
         
            -
                    unless current_node.linear.empty?
         
     | 
| 
       42 
     | 
    
         
            -
                      whole_path = parts.join('/')
         
     | 
| 
       43 
     | 
    
         
            -
                      next_node = current_node.linear.find do |(tester, node)|
         
     | 
| 
       44 
     | 
    
         
            -
                        if tester.is_a?(Regexp) and match = whole_path.match(tester)
         
     | 
| 
       45 
     | 
    
         
            -
                          whole_path.slice!(0,match[0].size)
         
     | 
| 
       46 
     | 
    
         
            -
                          parts.replace(@base.split(whole_path))
         
     | 
| 
       47 
     | 
    
         
            -
                          node
         
     | 
| 
       48 
     | 
    
         
            -
                        elsif new_params = tester.matches(parts, whole_path)
         
     | 
| 
       49 
     | 
    
         
            -
                          params << new_params
         
     | 
| 
       50 
     | 
    
         
            -
                          node
         
     | 
| 
       51 
     | 
    
         
            -
                        else
         
     | 
| 
       52 
     | 
    
         
            -
                          nil
         
     | 
| 
       53 
     | 
    
         
            -
                        end
         
     | 
| 
       54 
     | 
    
         
            -
                      end
         
     | 
| 
       55 
     | 
    
         
            -
                      if next_node
         
     | 
| 
       56 
     | 
    
         
            -
                        current_node = next_node.last
         
     | 
| 
       57 
     | 
    
         
            -
                        next
         
     | 
| 
       58 
     | 
    
         
            -
                      end
         
     | 
| 
       59 
     | 
    
         
            -
                    end
         
     | 
| 
       60 
     | 
    
         
            -
                    if match = current_node.lookup[parts.first]
         
     | 
| 
       61 
     | 
    
         
            -
                      parts.shift
         
     | 
| 
       62 
     | 
    
         
            -
                      current_node = match
         
     | 
| 
       63 
     | 
    
         
            -
                    elsif current_node.catchall
         
     | 
| 
       64 
     | 
    
         
            -
                      params << current_node.catchall.variable.matches(parts, whole_path)
         
     | 
| 
       65 
     | 
    
         
            -
                      parts.shift
         
     | 
| 
       66 
     | 
    
         
            -
                      current_node = current_node.catchall
         
     | 
| 
       67 
     | 
    
         
            -
                    elsif parts.size == 1 && parts.first == '' && current_node && (current_node.value && current_node.value.route.trailing_slash_ignore?)
         
     | 
| 
       68 
     | 
    
         
            -
                      parts.shift
         
     | 
| 
       69 
     | 
    
         
            -
                    elsif current_node.request_node
         
     | 
| 
       70 
     | 
    
         
            -
                      break
         
     | 
| 
       71 
     | 
    
         
            -
                    else
         
     | 
| 
       72 
     | 
    
         
            -
                      current_node = nil
         
     | 
| 
       73 
     | 
    
         
            -
                      break
         
     | 
| 
       74 
     | 
    
         
            -
                    end
         
     | 
| 
       75 
     | 
    
         
            -
                  end
         
     | 
| 
       76 
     | 
    
         
            -
                  current_node
         
     | 
| 
       77 
     | 
    
         
            -
                end
         
     | 
| 
       78 
     | 
    
         
            -
             
     | 
| 
       79 
28 
     | 
    
         
             
                def process_response(node, parts, extension, params, request)
         
     | 
| 
       80 
     | 
    
         
            -
                  if node. 
     | 
| 
      
 29 
     | 
    
         
            +
                  if node.respond_to?(:matched?) && !node.matched?
         
     | 
| 
       81 
30 
     | 
    
         
             
                    node
         
     | 
| 
       82 
31 
     | 
    
         
             
                  elsif node && node.value
         
     | 
| 
       83 
32 
     | 
    
         
             
                    if parts.empty?
         
     | 
| 
         @@ -103,10 +52,10 @@ class HttpRouter 
     | 
|
| 
       103 
52 
     | 
    
         | 
| 
       104 
53 
     | 
    
         
             
                def post_match(path, params, extension, matched_path, remaining_path = nil)
         
     | 
| 
       105 
54 
     | 
    
         
             
                  if path.route.partially_match? || path.matches_extension?(extension)
         
     | 
| 
       106 
     | 
    
         
            -
                    Response. 
     | 
| 
      
 55 
     | 
    
         
            +
                    Response.matched(path, params, extension, matched_path, remaining_path)
         
     | 
| 
       107 
56 
     | 
    
         
             
                  else
         
     | 
| 
       108 
57 
     | 
    
         
             
                    nil
         
     | 
| 
       109 
58 
     | 
    
         
             
                  end
         
     | 
| 
       110 
59 
     | 
    
         
             
                end
         
     | 
| 
       111 
60 
     | 
    
         
             
              end
         
     | 
| 
       112 
     | 
    
         
            -
            end
         
     | 
| 
      
 61 
     | 
    
         
            +
            end
         
     |