@@ -137,3 +137,35 @@ func TestReadBuiltinFile(t *testing.T) {
137137 require.NotContains(t, resp.Content, " 1|")
138138 })
139139}
140+
141+func TestSniffImageMimeType(t *testing.T) {
142+ t.Parallel()
143+
144+ jpegMagic := []byte{0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 'J', 'F', 'I', 'F'}
145+ pngMagic := []byte{0x89, 'P', 'N', 'G', 0x0d, 0x0a, 0x1a, 0x0a}
146+ gifMagic := []byte("GIF89a")
147+ // Minimal RIFF/WEBP header.
148+ webpMagic := append([]byte("RIFF\x00\x00\x00\x00WEBPVP8 "), make([]byte, 16)...)
149+ random := []byte("not an image at all, just text")
150+
151+ cases := []struct {
152+ name string
153+ data []byte
154+ fallback string
155+ want string
156+ }{
157+ {"jpeg bytes in .png file uses sniffed", jpegMagic, "image/png", "image/jpeg"},
158+ {"png bytes in .jpg file uses sniffed", pngMagic, "image/jpeg", "image/png"},
159+ {"gif bytes uses sniffed", gifMagic, "image/png", "image/gif"},
160+ {"webp bytes uses sniffed", webpMagic, "image/png", "image/webp"},
161+ {"matching extension and content keeps sniffed", pngMagic, "image/png", "image/png"},
162+ {"unsniffable content falls back", random, "image/png", "image/png"},
163+ {"empty content falls back", nil, "image/jpeg", "image/jpeg"},
164+ }
165+ for _, tc := range cases {
166+ t.Run(tc.name, func(t *testing.T) {
167+ t.Parallel()
168+ require.Equal(t, tc.want, sniffImageMimeType(tc.data, tc.fallback))
169+ })
170+ }
171+}