mimeTypesLower sync.Map // map[string]string; ".z" => "application/x-compress"
// extensions maps from MIME type to list of lowercase file
- // extensions: "image/jpeg" => [".jpg", ".jpeg"]
+ // extensions: "image/jpeg" => [".jfif", ".jpg", ".jpeg", ".pjp", ".pjpeg"]
extensionsMu sync.Mutex // Guards stores (but not loads) on extensions.
extensions sync.Map // map[string][]string; slice values are append-only.
)
}
}
+// A type is listed here if both Firefox and Chrome included them in their own
+// lists. In the case where they contradict they are deconflicted using IANA's
+// listed media types https://www.iana.org/assignments/media-types/media-types.xhtml
+//
+// Chrome's MIME mappings to file extensions are defined at
+// https://chromium.googlesource.com/chromium/src.git/+/refs/heads/main/net/base/mime_util.cc
+//
+// Firefox's MIME types can be found at
+// https://github.com/mozilla-firefox/firefox/blob/main/netwerk/mime/nsMimeTypes.h
+// and the mappings to file extensions at
+// https://github.com/mozilla-firefox/firefox/blob/main/uriloader/exthandler/nsExternalHelperAppService.cpp
var builtinTypesLower = map[string]string{
- ".avif": "image/avif",
- ".css": "text/css; charset=utf-8",
- ".gif": "image/gif",
- ".htm": "text/html; charset=utf-8",
- ".html": "text/html; charset=utf-8",
- ".jpeg": "image/jpeg",
- ".jpg": "image/jpeg",
- ".js": "text/javascript; charset=utf-8",
- ".json": "application/json",
- ".mjs": "text/javascript; charset=utf-8",
- ".pdf": "application/pdf",
- ".png": "image/png",
- ".svg": "image/svg+xml",
- ".wasm": "application/wasm",
- ".webp": "image/webp",
- ".xml": "text/xml; charset=utf-8",
+ ".ai": "application/postscript",
+ ".apk": "application/vnd.android.package-archive",
+ ".apng": "image/apng",
+ ".avif": "image/avif",
+ ".bin": "application/octet-stream",
+ ".bmp": "image/bmp",
+ ".com": "application/octet-stream",
+ ".css": "text/css; charset=utf-8",
+ ".csv": "text/csv; charset=utf-8",
+ ".doc": "application/msword",
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ ".ehtml": "text/html; charset=utf-8",
+ ".eml": "message/rfc822",
+ ".eps": "application/postscript",
+ ".exe": "application/octet-stream",
+ ".flac": "audio/flac",
+ ".gif": "image/gif",
+ ".gz": "application/gzip",
+ ".htm": "text/html; charset=utf-8",
+ ".html": "text/html; charset=utf-8",
+ ".ico": "image/vnd.microsoft.icon",
+ ".ics": "text/calendar; charset=utf-8",
+ ".jfif": "image/jpeg",
+ ".jpeg": "image/jpeg",
+ ".jpg": "image/jpeg",
+ ".js": "text/javascript; charset=utf-8",
+ ".json": "application/json",
+ ".m4a": "audio/mp4",
+ ".mjs": "text/javascript; charset=utf-8",
+ ".mp3": "audio/mpeg",
+ ".mp4": "video/mp4",
+ ".oga": "audio/ogg",
+ ".ogg": "audio/ogg",
+ ".ogv": "video/ogg",
+ ".opus": "audio/ogg",
+ ".pdf": "application/pdf",
+ ".pjp": "image/jpeg",
+ ".pjpeg": "image/jpeg",
+ ".png": "image/png",
+ ".ppt": "application/vnd.ms-powerpoint",
+ ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
+ ".ps": "application/postscript",
+ ".rdf": "application/rdf+xml",
+ ".rtf": "application/rtf",
+ ".shtml": "text/html; charset=utf-8",
+ ".svg": "image/svg+xml",
+ ".text": "text/plain; charset=utf-8",
+ ".tif": "image/tiff",
+ ".tiff": "image/tiff",
+ ".txt": "text/plain; charset=utf-8",
+ ".vtt": "text/vtt; charset=utf-8",
+ ".wasm": "application/wasm",
+ ".wav": "audio/wav",
+ ".webm": "audio/webm",
+ ".webp": "image/webp",
+ ".xbl": "text/xml; charset=utf-8",
+ ".xbm": "image/x-xbitmap",
+ ".xht": "application/xhtml+xml",
+ ".xhtml": "application/xhtml+xml",
+ ".xls": "application/vnd.ms-excel",
+ ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ ".xml": "text/xml; charset=utf-8",
+ ".xsl": "text/xml; charset=utf-8",
+ ".zip": "application/zip",
}
var once sync.Once // guards initMime
typ string
want []string
}{
- {typ: "image/jpeg", want: []string{".jpeg", ".jpg"}},
+ {typ: "application/postscript", want: []string{".ai", ".eps", ".ps"}},
+ {typ: "application/vnd.android.package-archive", want: []string{".apk"}},
+ {typ: "image/apng", want: []string{".apng"}},
+ {typ: "image/avif", want: []string{".avif"}},
+ {typ: "application/octet-stream", want: []string{".bin", ".com", ".exe"}},
+ {typ: "image/bmp", want: []string{".bmp"}},
+ {typ: "text/css; charset=utf-8", want: []string{".css"}},
+ {typ: "text/csv; charset=utf-8", want: []string{".csv"}},
+ {typ: "application/msword", want: []string{".doc"}},
+ {typ: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", want: []string{".docx"}},
+ {typ: "text/html; charset=utf-8", want: []string{".ehtml", ".htm", ".html", ".shtml"}},
+ {typ: "message/rfc822", want: []string{".eml"}},
+ {typ: "audio/flac", want: []string{".flac"}},
+ {typ: "image/gif", want: []string{".gif"}},
+ {typ: "application/gzip", want: []string{".gz"}},
+ {typ: "image/vnd.microsoft.icon", want: []string{".ico"}},
+ {typ: "text/calendar; charset=utf-8", want: []string{".ics"}},
+ {typ: "image/jpeg", want: []string{".jfif", ".jpeg", ".jpg", ".pjp", ".pjpeg"}},
+ {typ: "text/javascript; charset=utf-8", want: []string{".js", ".mjs"}},
+ {typ: "application/json", want: []string{".json"}},
+ {typ: "audio/mp4", want: []string{".m4a"}},
+ {typ: "audio/mpeg", want: []string{".mp3"}},
+ {typ: "video/mp4", want: []string{".mp4"}},
+ {typ: "audio/ogg", want: []string{".oga", ".ogg", ".opus"}},
+ {typ: "video/ogg", want: []string{".ogv"}},
+ {typ: "application/pdf", want: []string{".pdf"}},
+ {typ: "image/png", want: []string{".png"}},
+ {typ: "application/vnd.ms-powerpoint", want: []string{".ppt"}},
+ {typ: "application/vnd.openxmlformats-officedocument.presentationml.presentation", want: []string{".pptx"}},
+ {typ: "application/rdf+xml", want: []string{".rdf"}},
+ {typ: "application/rtf", want: []string{".rtf"}},
+ {typ: "image/svg+xml", want: []string{".svg"}},
+ {typ: "text/plain; charset=utf-8", want: []string{".text", ".txt"}},
+ {typ: "image/tiff", want: []string{".tif", ".tiff"}},
+ {typ: "text/vtt; charset=utf-8", want: []string{".vtt"}},
+ {typ: "application/wasm", want: []string{".wasm"}},
+ {typ: "audio/wav", want: []string{".wav"}},
+ {typ: "audio/webm", want: []string{".webm"}},
+ {typ: "image/webp", want: []string{".webp"}},
+ {typ: "text/xml; charset=utf-8", want: []string{".xbl", ".xml", ".xsl"}},
+ {typ: "image/x-xbitmap", want: []string{".xbm"}},
+ {typ: "application/xhtml+xml", want: []string{".xht", ".xhtml"}},
+ {typ: "application/vnd.ms-excel", want: []string{".xls"}},
+ {typ: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", want: []string{".xlsx"}},
+ {typ: "application/zip", want: []string{".zip"}},
}
for _, tt := range tests {