From 16e92fa5811f90bca5afae042b7caeb223dd8906 Mon Sep 17 00:00:00 2001 From: Toni Dahl <988779+K1ll3rF0x@users.noreply.github.com> Date: Wed, 10 Mar 2021 23:42:09 +0200 Subject: [PATCH] Guess and add correct "Content-Type" headers for responses. (#750) [skip ci] * A correct MIME type of a served file is guessed by file extension. * For example, SVG images are now displayed correctly in a web browser. --- examples/file-server.clj | 116 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/examples/file-server.clj b/examples/file-server.clj index 65284357..d8fa3f72 100755 --- a/examples/file-server.clj +++ b/examples/file-server.clj @@ -37,6 +37,119 @@ (assert (fs/directory? dir) (str "The given dir `" dir "` is not a directory.")) +;; A simple mime type utility from https://github.com/ring-clojure/ring/blob/master/ring-core/src/ring/util/mime_type.clj +(def ^{:doc "A map of file extensions to mime-types."} + default-mime-types + {"7z" "application/x-7z-compressed" + "aac" "audio/aac" + "ai" "application/postscript" + "appcache" "text/cache-manifest" + "asc" "text/plain" + "atom" "application/atom+xml" + "avi" "video/x-msvideo" + "bin" "application/octet-stream" + "bmp" "image/bmp" + "bz2" "application/x-bzip" + "class" "application/octet-stream" + "cer" "application/pkix-cert" + "crl" "application/pkix-crl" + "crt" "application/x-x509-ca-cert" + "css" "text/css" + "csv" "text/csv" + "deb" "application/x-deb" + "dart" "application/dart" + "dll" "application/octet-stream" + "dmg" "application/octet-stream" + "dms" "application/octet-stream" + "doc" "application/msword" + "dvi" "application/x-dvi" + "edn" "application/edn" + "eot" "application/vnd.ms-fontobject" + "eps" "application/postscript" + "etx" "text/x-setext" + "exe" "application/octet-stream" + "flv" "video/x-flv" + "flac" "audio/flac" + "gif" "image/gif" + "gz" "application/gzip" + "htm" "text/html" + "html" "text/html" + "ico" "image/x-icon" + "iso" "application/x-iso9660-image" + "jar" "application/java-archive" + "jpe" "image/jpeg" + "jpeg" "image/jpeg" + "jpg" "image/jpeg" + "js" "text/javascript" + "json" "application/json" + "lha" "application/octet-stream" + "lzh" "application/octet-stream" + "mov" "video/quicktime" + "m3u8" "application/x-mpegurl" + "m4v" "video/mp4" + "mjs" "text/javascript" + "mp3" "audio/mpeg" + "mp4" "video/mp4" + "mpd" "application/dash+xml" + "mpe" "video/mpeg" + "mpeg" "video/mpeg" + "mpg" "video/mpeg" + "oga" "audio/ogg" + "ogg" "audio/ogg" + "ogv" "video/ogg" + "pbm" "image/x-portable-bitmap" + "pdf" "application/pdf" + "pgm" "image/x-portable-graymap" + "png" "image/png" + "pnm" "image/x-portable-anymap" + "ppm" "image/x-portable-pixmap" + "ppt" "application/vnd.ms-powerpoint" + "ps" "application/postscript" + "qt" "video/quicktime" + "rar" "application/x-rar-compressed" + "ras" "image/x-cmu-raster" + "rb" "text/plain" + "rd" "text/plain" + "rss" "application/rss+xml" + "rtf" "application/rtf" + "sgm" "text/sgml" + "sgml" "text/sgml" + "svg" "image/svg+xml" + "swf" "application/x-shockwave-flash" + "tar" "application/x-tar" + "tif" "image/tiff" + "tiff" "image/tiff" + "ts" "video/mp2t" + "ttf" "font/ttf" + "txt" "text/plain" + "webm" "video/webm" + "wmv" "video/x-ms-wmv" + "woff" "font/woff" + "woff2" "font/woff2" + "xbm" "image/x-xbitmap" + "xls" "application/vnd.ms-excel" + "xml" "text/xml" + "xpm" "image/x-xpixmap" + "xwd" "image/x-xwindowdump" + "zip" "application/zip"}) + +;; https://github.com/ring-clojure/ring/blob/master/ring-core/src/ring/util/mime_type.clj +(defn- filename-ext + "Returns the file extension of a filename or filepath." + [filename] + (if-let [ext (second (re-find #"\.([^./\\]+)$" filename))] + (str/lower-case ext))) + +;; https://github.com/ring-clojure/ring/blob/master/ring-core/src/ring/util/mime_type.clj +(defn ext-mime-type + "Get the mimetype from the filename extension. Takes an optional map of + extensions to mimetypes that overrides values in the default-mime-types map." + ([filename] + (ext-mime-type filename {})) + ([filename mime-types] + (let [mime-types (merge default-mime-types mime-types)] + (mime-types (filename-ext filename))))) + (defn index [f] (let [files (map #(str (.relativize dir %)) (fs/list-dir f))] @@ -56,7 +169,8 @@ str)})) (defn body [path] - {:body (fs/file path)}) + {:headers {"Content-Type" (ext-mime-type (fs/file-name path))} + :body (fs/file path)}) (server/run-server (fn [{:keys [:uri]}]