Skip to content

Commit

Permalink
Allow conflicting extensions to be configured
Browse files Browse the repository at this point in the history
  • Loading branch information
josevalim committed Jun 1, 2023
1 parent 90852eb commit b856c1e
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 23 deletions.
41 changes: 27 additions & 14 deletions lib/mime.ex
Original file line number Diff line number Diff line change
Expand Up @@ -130,24 +130,21 @@ defmodule MIME do

to_exts = fn map ->
for {media, exts} <- map, ext <- exts, reduce: %{} do
acc -> Map.update(acc, ext, [media], &[media | &1])
acc -> Map.update(acc, ext, media, &[media | List.wrap(&1)])
end
end

all_types = Map.merge(types, custom_types)

all_exts =
Map.merge(to_exts.(all_types), %{
"3g2" => ["video/3gpp2"],
"3gp" => ["video/3gpp"],
"js" => ["text/javascript"],
"xml" => ["text/xml"]
})

for {ext, [_, _ | _] = mimes} <- all_exts do
raise "conflicting MIMEs for extension .#{ext}, please override: #{inspect(mimes)}"
end
default_exts = %{
"3g2" => "video/3gpp2",
"3gp" => "video/3gpp",
"js" => "text/javascript",
"xml" => "text/xml"
}

custom_exts = Application.compile_env(:mime, :extensions, %{})
all_exts = Map.merge(to_exts.(all_types), Map.merge(default_exts, custom_exts))

# https://www.iana.org/assignments/media-type-structured-suffix/media-type-structured-suffix.xhtml
default_suffixes = %{
Expand Down Expand Up @@ -271,8 +268,24 @@ defmodule MIME do
@spec ext_to_mime(String.t()) :: String.t() | nil
defp ext_to_mime(type)

for {ext, [type | _]} <- all_exts do
defp ext_to_mime(unquote(ext)), do: unquote(type)
for {ext, mimes} <- all_exts do
case mimes do
[first | _] ->
raise """
extension .#{ext} currently maps to different mime-types: #{inspect(mimes)}
You must tell us which mime-type is preferred by defining the :extensions \
configuration. For example:
config :mime, :extensions, %{
#{inspect(ext)} => #{inspect(first)}
}
"""

mime ->
defp ext_to_mime(unquote(ext)), do: unquote(mime)
end
end

defp ext_to_mime(_ext), do: nil
Expand Down
33 changes: 24 additions & 9 deletions test/mime_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ defmodule MIMETest do
import MIME
doctest MIME

defp recompile! do
[File.cwd!(), "lib", "mime.ex"]
|> Path.join()
|> Code.compile_file()
end

test "extensions/1" do
assert extensions("application/json; charset=utf-8") == ["json"]
assert extensions("application/json") == ["json"]
Expand Down Expand Up @@ -57,25 +63,34 @@ defmodule MIMETest do
end)
end

test "overrides extensions" do
test "overrides types" do
Application.put_env(:mime, :types, %{"text/plain" => ["env"]})

[File.cwd!(), "lib", "mime.ex"]
|> Path.join()
|> Code.compile_file()
recompile!()

assert MIME.extensions("text/plain") == ["env"]
assert MIME.type("env") == "text/plain"
assert MIME.type("txt") == "application/octet-stream"
assert MIME.type("text") == "application/octet-stream"
end

test "overrides extensions" do
Application.put_env(:mime, :types, %{"audio/x-wav" => ["wav"]})

assert_raise RuntimeError,
~r"You must tell us which mime-type is preferred by defining the :extensions configuration",
fn -> recompile!() end

Application.put_env(:mime, :extensions, %{"wav" => "audio/x-wav"})
recompile!()

assert MIME.extensions("audio/wav") == ["wav"]
assert MIME.extensions("audio/x-wav") == ["wav"]
assert MIME.type("wav") == "audio/x-wav"
end

test "overrides suffixes" do
Application.put_env(:mime, :suffixes, %{"custom-format" => ["cf"]})

[File.cwd!(), "lib", "mime.ex"]
|> Path.join()
|> Code.compile_file()
recompile!()

assert MIME.extensions("text/plain+custom-format") == ["cf"]
end
Expand Down

0 comments on commit b856c1e

Please sign in to comment.