summary refs log tree commit
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2015-09-04 14:18:16 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2015-09-04 14:18:16 -0700
commit568cf7294d3c8abb84825514e91cf98c58a5e503 (patch)
tree1f0fb9dec64674238fcca2043ebdacd8c4dc5f61
parent978eb9b9935d388ca8cc45fe31c870b9bc0aaab2 (diff)
downloadrack-568cf7294d3c8abb84825514e91cf98c58a5e503.tar.gz
use `Rack::Utils.unescape_path` to unescape path_info
Unescaping paths is different from unescaping query parameters.  This
commit changes the unescape to use the URI parser to unescape the path,
which leaves `+` as `+`.

Fixes #265
References rails/rails#11816
-rw-r--r--HISTORY.md6
-rw-r--r--lib/rack/file.rb2
-rw-r--r--test/spec_file.rb15
3 files changed, 22 insertions, 1 deletions
diff --git a/HISTORY.md b/HISTORY.md
index 232cf038..2e7e698b 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,3 +1,9 @@
+Fri Sep  4 14:15:32 2015  Aaron Patterson <tenderlove@ruby-lang.org>
+
+        * Files and directories with + in the name are served correctly.
+        Rather than unescaping paths like a form, we unescape with a URI
+        parser using `Rack::Utils.unescape_path`. Fixes #265
+
 Thu Aug 27 15:43:48 2015  Aaron Patterson <tenderlove@ruby-lang.org>
 
         * Tempfiles are automatically closed in the case that there were too
diff --git a/lib/rack/file.rb b/lib/rack/file.rb
index 1efa15a7..5b755f56 100644
--- a/lib/rack/file.rb
+++ b/lib/rack/file.rb
@@ -30,7 +30,7 @@ module Rack
         return fail(405, "Method Not Allowed", {'Allow' => ALLOW_HEADER})
       end
 
-      path_info = Utils.unescape request.path_info
+      path_info = Utils.unescape_path request.path_info
       clean_path_info = Utils.clean_path_info(path_info)
 
       path = ::File.join(@root, clean_path_info)
diff --git a/test/spec_file.rb b/test/spec_file.rb
index 71828b90..2d0919a9 100644
--- a/test/spec_file.rb
+++ b/test/spec_file.rb
@@ -10,6 +10,21 @@ describe Rack::File do
     Rack::Lint.new Rack::File.new(*args)
   end
 
+  it 'serves files with + in the file name' do
+    Dir.mktmpdir do |dir|
+      File.write File.join(dir, "you+me.txt"), "hello world"
+      app = file(dir)
+      env = Rack::MockRequest.env_for("/you+me.txt")
+      status,_,body = app.call env
+
+      assert_equal 200, status
+
+      str = ''
+      body.each { |x| str << x }
+      assert_match "hello world", str
+    end
+  end
+
   it "serve files" do
     res = Rack::MockRequest.new(file(DOCROOT)).get("/cgi/test")