I've been playing around with Phoenix and I want to provide a download link to a PDF file:
The following code works fine in my dev environment. When I click on the link a PDF file is downloaded.
case File.read(localpath) do
{:ok, pdf_content} ->
conn
|> put_resp_header("Content-Type", "application/pdf")
|> put_resp_header("Content-Disposition", ~s[attachment; filename="#{file}"])
|>200, pdf_content)
{:error, _} ->
conn
|>:not_found, "Not Found")
end
However when I run tests to verify the behaviour I'll get an error:
** (Plug.Conn.InvalidHeaderError) header key is not lowercase: "Content-Type"
stacktrace:
(plug) lib/plug/conn.ex:957: Plug.Conn.validate_header_key!/2
(plug) lib/plug/conn.ex:556: Plug.Conn.put_resp_header/3
This seems weird to me for 2 reasons:
The reason this error is only raised in the test environment can be seen in the source code for Plug.Conn
, specifically these lines:
defp validate_header_key!({Plug.Adapters.Test.Conn, _}, key) do
unless valid_header_key?(key) do
raise InvalidHeaderError, message: "header key is not lowercase: " <> inspect(key)
end
end
defp validate_header_key!(_adapter, _key) do
:ok
end
As this code shows, the header key is actually validated only if the adapter is Plug's test adapter. The reason this only happens in the test environment is because it can be expensive to perform these validations on the headers and so they are skipped in non-test environments. This commit is the commit where the restriction on validating only in the test environment was introduced.
By the way, the header doesn't have to be lowercase (as you can tell by the fact that it works in non-test environments), but I think that by Plug's convention it should be.