summary refs log tree commit
diff options
context:
space:
mode:
authorJoshua Peek <josh@joshpeek.com>2009-12-26 11:17:52 -0600
committerJoshua Peek <josh@joshpeek.com>2009-12-26 11:17:52 -0600
commit8e6bc663d1a72f717dc913faf72cc84097da8f8a (patch)
tree168412e42481d9859118ff9d0baf4fc95f03f68e
parent99acee31104cb2cc0e3adb1c25a9a29dfc510619 (diff)
parent065ba85cc49a15d952c46410aad4ef78a98f7717 (diff)
downloadrack-8e6bc663d1a72f717dc913faf72cc84097da8f8a.tar.gz
Merge remote branch 'origin/nosqueeze'
-rw-r--r--lib/rack/urlmap.rb15
-rw-r--r--test/spec_rack_urlmap.rb30
2 files changed, 38 insertions, 7 deletions
diff --git a/lib/rack/urlmap.rb b/lib/rack/urlmap.rb
index 262dec8d..b699d35b 100644
--- a/lib/rack/urlmap.rb
+++ b/lib/rack/urlmap.rb
@@ -28,25 +28,26 @@ module Rack
           raise ArgumentError, "paths need to start with /"
         end
         location = location.chomp('/')
+        match = Regexp.new("^#{Regexp.quote(location).gsub('/', '/+')}(.*)", nil, 'n')
 
-        [host, location, app]
-      }.sort_by { |(h, l, a)| [h ? -h.size : (-1.0 / 0.0), -l.size] }  # Longest path first
+        [host, location, match, app]
+      }.sort_by { |(h, l, m, a)| [h ? -h.size : (-1.0 / 0.0), -l.size] }  # Longest path first
     end
 
     def call(env)
-      path = env["PATH_INFO"].to_s.squeeze("/")
+      path = env["PATH_INFO"].to_s
       script_name = env['SCRIPT_NAME']
       hHost, sName, sPort = env.values_at('HTTP_HOST','SERVER_NAME','SERVER_PORT')
-      @mapping.each { |host, location, app|
+      @mapping.each { |host, location, match, app|
         next unless (hHost == host || sName == host \
           || (host.nil? && (hHost == sName || hHost == sName+':'+sPort)))
-        next unless location == path[0, location.size]
-        next unless path[location.size] == nil || path[location.size] == ?/
+        next unless path =~ match && rest = $1
+        next unless rest.empty? || rest[0] == ?/
 
         return app.call(
           env.merge(
             'SCRIPT_NAME' => (script_name + location),
-            'PATH_INFO'   => path[location.size..-1]))
+            'PATH_INFO'   => rest))
       }
       [404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"}, ["Not Found: #{path}"]]
     end
diff --git a/test/spec_rack_urlmap.rb b/test/spec_rack_urlmap.rb
index 6c4d72ac..3d8fe605 100644
--- a/test/spec_rack_urlmap.rb
+++ b/test/spec_rack_urlmap.rb
@@ -44,6 +44,12 @@ context "Rack::URLMap" do
     res["X-ScriptName"].should.equal "/foo/bar"
     res["X-PathInfo"].should.equal "/"
 
+    res = Rack::MockRequest.new(map).get("/foo///bar//quux")
+    res.status.should.equal 200
+    res.should.be.ok
+    res["X-ScriptName"].should.equal "/foo/bar"
+    res["X-PathInfo"].should.equal "//quux"
+
     res = Rack::MockRequest.new(map).get("/foo/quux", "SCRIPT_NAME" => "/bleh")
     res.should.be.ok
     res["X-ScriptName"].should.equal "/bleh/foo"
@@ -182,4 +188,28 @@ context "Rack::URLMap" do
     res["X-PathInfo"].should.equal "/"
     res["X-ScriptName"].should.equal ""
   end
+
+  specify "should not squeeze slashes" do
+    map = Rack::URLMap.new("/" => lambda { |env|
+                             [200,
+                              { "Content-Type" => "text/plain",
+                                "X-Position" => "root",
+                                "X-PathInfo" => env["PATH_INFO"],
+                                "X-ScriptName" => env["SCRIPT_NAME"]
+                              }, [""]]},
+                           "/foo" => lambda { |env|
+                             [200,
+                              { "Content-Type" => "text/plain",
+                                "X-Position" => "foo",
+                                "X-PathInfo" => env["PATH_INFO"],
+                                "X-ScriptName" => env["SCRIPT_NAME"]
+                              }, [""]]}
+                           )
+
+    res = Rack::MockRequest.new(map).get("/http://example.org/bar")
+    res.should.be.ok
+    res["X-Position"].should.equal "root"
+    res["X-PathInfo"].should.equal "/http://example.org/bar"
+    res["X-ScriptName"].should.equal ""
+  end
 end