Skip to content

Commit

Permalink
Fix duplicate Content-Type header with Rack 2
Browse files Browse the repository at this point in the history
Previously, `ActionDispatch::Static` would always merge a "content-type"
header into the headers returned from `Rack::Files`. However, this would
potentially lead to both a "Content-Type" header and a "content-type"
header when using Rack 2.

This commit fixes the issue by using `Rack::CONTENT_TYPE` to determine
which version of the header to set in `ActionDispatch::Static`. In both
versions of Rack it will use the same version of the header as
`Rack::Files`.

The tests added have to use `@app.call` instead of
`get()`/`Rack::MockRequest` because `Rack::Response` actually does the
correct thing already by using `Rack::Util::HeaderHash` so it covers up
the issue in tests.
  • Loading branch information
skipkayhil committed Jun 9, 2023
1 parent fdad62b commit f7c6e2c
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 1 deletion.
2 changes: 1 addition & 1 deletion actionpack/lib/action_dispatch/middleware/static.rb
Expand Up @@ -108,7 +108,7 @@ def find_file(path_info, accept_encoding:)
end

def try_files(filepath, content_type, accept_encoding:)
headers = { "content-type" => content_type }
headers = { Rack::CONTENT_TYPE => content_type }

if compressible? content_type
try_precompressed_files filepath, headers, accept_encoding: accept_encoding
Expand Down
12 changes: 12 additions & 0 deletions actionpack/test/dispatch/static_test.rb
Expand Up @@ -199,6 +199,18 @@ def test_does_not_modify_path_info
assert_equal file_name, env["PATH_INFO"]
end

def test_only_set_one_content_type
file_name = "/gzip/foo.zoo"
gzip_env = { "PATH_INFO" => file_name, "HTTP_ACCEPT_ENCODING" => "gzip", "REQUEST_METHOD" => "GET" }
response = @app.call(gzip_env)

env = { "PATH_INFO" => file_name, "REQUEST_METHOD" => "GET" }
default_response = @app.call(env)

assert_equal 1, response[1].slice("Content-Type", "content-type").size
assert_equal 1, default_response[1].slice("Content-Type", "content-type").size
end

def test_serves_gzip_with_proper_content_type_fallback
file_name = "/gzip/foo.zoo"
response = get(file_name, "HTTP_ACCEPT_ENCODING" => "gzip")
Expand Down

0 comments on commit f7c6e2c

Please sign in to comment.