Skip to content

Commit b856c1e

Browse files
committed
Allow conflicting extensions to be configured
1 parent 90852eb commit b856c1e

File tree

2 files changed

+51
-23
lines changed

2 files changed

+51
-23
lines changed

lib/mime.ex

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -130,24 +130,21 @@ defmodule MIME do
130130

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

137137
all_types = Map.merge(types, custom_types)
138138

139-
all_exts =
140-
Map.merge(to_exts.(all_types), %{
141-
"3g2" => ["video/3gpp2"],
142-
"3gp" => ["video/3gpp"],
143-
"js" => ["text/javascript"],
144-
"xml" => ["text/xml"]
145-
})
146-
147-
for {ext, [_, _ | _] = mimes} <- all_exts do
148-
raise "conflicting MIMEs for extension .#{ext}, please override: #{inspect(mimes)}"
149-
end
139+
default_exts = %{
140+
"3g2" => "video/3gpp2",
141+
"3gp" => "video/3gpp",
142+
"js" => "text/javascript",
143+
"xml" => "text/xml"
144+
}
150145

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

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

274-
for {ext, [type | _]} <- all_exts do
275-
defp ext_to_mime(unquote(ext)), do: unquote(type)
271+
for {ext, mimes} <- all_exts do
272+
case mimes do
273+
[first | _] ->
274+
raise """
275+
extension .#{ext} currently maps to different mime-types: #{inspect(mimes)}
276+
277+
You must tell us which mime-type is preferred by defining the :extensions \
278+
configuration. For example:
279+
280+
config :mime, :extensions, %{
281+
#{inspect(ext)} => #{inspect(first)}
282+
}
283+
284+
"""
285+
286+
mime ->
287+
defp ext_to_mime(unquote(ext)), do: unquote(mime)
288+
end
276289
end
277290

278291
defp ext_to_mime(_ext), do: nil

test/mime_test.exs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ defmodule MIMETest do
44
import MIME
55
doctest MIME
66

7+
defp recompile! do
8+
[File.cwd!(), "lib", "mime.ex"]
9+
|> Path.join()
10+
|> Code.compile_file()
11+
end
12+
713
test "extensions/1" do
814
assert extensions("application/json; charset=utf-8") == ["json"]
915
assert extensions("application/json") == ["json"]
@@ -57,25 +63,34 @@ defmodule MIMETest do
5763
end)
5864
end
5965

60-
test "overrides extensions" do
66+
test "overrides types" do
6167
Application.put_env(:mime, :types, %{"text/plain" => ["env"]})
62-
63-
[File.cwd!(), "lib", "mime.ex"]
64-
|> Path.join()
65-
|> Code.compile_file()
68+
recompile!()
6669

6770
assert MIME.extensions("text/plain") == ["env"]
6871
assert MIME.type("env") == "text/plain"
6972
assert MIME.type("txt") == "application/octet-stream"
7073
assert MIME.type("text") == "application/octet-stream"
7174
end
7275

76+
test "overrides extensions" do
77+
Application.put_env(:mime, :types, %{"audio/x-wav" => ["wav"]})
78+
79+
assert_raise RuntimeError,
80+
~r"You must tell us which mime-type is preferred by defining the :extensions configuration",
81+
fn -> recompile!() end
82+
83+
Application.put_env(:mime, :extensions, %{"wav" => "audio/x-wav"})
84+
recompile!()
85+
86+
assert MIME.extensions("audio/wav") == ["wav"]
87+
assert MIME.extensions("audio/x-wav") == ["wav"]
88+
assert MIME.type("wav") == "audio/x-wav"
89+
end
90+
7391
test "overrides suffixes" do
7492
Application.put_env(:mime, :suffixes, %{"custom-format" => ["cf"]})
75-
76-
[File.cwd!(), "lib", "mime.ex"]
77-
|> Path.join()
78-
|> Code.compile_file()
93+
recompile!()
7994

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

0 commit comments

Comments
 (0)