From 568cf7294d3c8abb84825514e91cf98c58a5e503 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 4 Sep 2015 14:18:16 -0700 Subject: [PATCH] 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 --- HISTORY.md | 6 ++++++ lib/rack/file.rb | 2 +- test/spec_file.rb | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 232cf0383..2e7e698b5 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,9 @@ +Fri Sep 4 14:15:32 2015 Aaron Patterson + + * 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 * Tempfiles are automatically closed in the case that there were too diff --git a/lib/rack/file.rb b/lib/rack/file.rb index 1efa15a7d..5b755f563 100644 --- a/lib/rack/file.rb +++ b/lib/rack/file.rb @@ -30,7 +30,7 @@ def call(env) 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 71828b900..2d0919a92 100644 --- a/test/spec_file.rb +++ b/test/spec_file.rb @@ -10,6 +10,21 @@ def file(*args) 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")