Skip to content

Commit 8ca5f09

Browse files
lrennweavejester
authored andcommitted
with-mimetypes middleware.
Middleware to add the proper Content-Type header based on the uri of the request. options is a map containing a :mimetype map of extension to type and a :default mime type. If :mimetype is not provided, a default map with common mime types will be used. If :default is not provided, "text/html" is used. Signed-off-by: James Reeves <jreeves@weavejester.com>
1 parent a45940a commit 8ca5f09

2 files changed

Lines changed: 70 additions & 0 deletions

File tree

src/compojure/http/middleware.clj

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"Various middleware functions."
1111
(:use compojure.http.routes)
1212
(:use compojure.str-utils)
13+
(:use clojure.contrib.def)
1314
(:use clojure.contrib.str-utils))
1415

1516
(defn header-option
@@ -44,3 +45,45 @@
4445
[handler header-map]
4546
(with-headers handler
4647
{"Cache-Control" (header-options header-map ", ")}))
48+
49+
(defvar default-mimetypes
50+
{"css" "text/css"
51+
"gif" "image/gif"
52+
"htm" "text/html"
53+
"html" "text/html"
54+
"jpg" "image/jpeg"
55+
"js" "text/javascript"
56+
"pdf" "application/pdf"
57+
"png" "image/png"
58+
"swf" "application/x-shockwave-flash"
59+
"txt" "text/plain"
60+
"xml" "text/xml"
61+
"zip" "application/zip"}
62+
"Default mimetype map used by with-mimetypes.")
63+
64+
(defn- extension
65+
"Returns the text after the last . of a String or nil."
66+
[s]
67+
(second (re-find #"\.(.*$)" s)))
68+
69+
(defn- request-mimetype
70+
"Derives the mimetype from a request. See with-mimetypes for options."
71+
[request options]
72+
(let [default (or (:default options) "text/html")]
73+
(if-let [ext (extension (:uri request))]
74+
(let [mimetypes (or (:mimetypes options) default-mimetypes)]
75+
(get mimetypes ext default))
76+
default)))
77+
78+
(defn with-mimetypes
79+
"Middleware to add the proper Content-Type header based on the uri of
80+
the request. options is a map containing a :mimetype map of extension
81+
to type and a :default mime type. If :mimetype is not provided, a default
82+
map with common mime types will be used. If :default is not provided,
83+
\"text/html\" is used."
84+
([handler]
85+
(with-mimetypes handler {}))
86+
([handler options]
87+
(fn [request]
88+
(let [mimetype (request-mimetype request options)]
89+
((with-headers handler {"Content-Type" mimetype}) request)))))

test/compojure/http/middleware.clj

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,30 @@
5050
(let [response (mock-middleware-response with-cache-control m)]
5151
(is (= "max-age=3600, must-revalidate"
5252
(get (:headers response) "Cache-Control"))))))
53+
54+
(defn run-mimetypes
55+
[uri type options]
56+
(let [routes (routes (GET uri "foo"))
57+
request {:request-method :get,
58+
:uri uri}
59+
response ((with-mimetypes routes options) request)
60+
result (get (:headers response) "Content-Type")]
61+
(= type result)))
62+
63+
(deftest test-with-default-mimetypes
64+
(are (run-mimetypes _1 _2 {})
65+
"/" "text/html"
66+
"/foobar" "text/html"
67+
"/file.pdf" "application/pdf"
68+
"/files/bar.css" "text/css"))
69+
70+
(deftest test-with-custom-mimetypes
71+
(let [options {:mimetypes {"foo" "test/foo"
72+
"bar" "test/bar"}
73+
:default "test/default"}]
74+
(are (run-mimetypes _1 _2 options)
75+
"/" "test/default"
76+
"/foobar" "test/default"
77+
"/file.pdf" "test/default"
78+
"/file.foo" "test/foo"
79+
"/files/file.bar" "test/bar")))

0 commit comments

Comments
 (0)