Permalink
Browse files

Refactor static file handling to unify ring.middleware.file and ring.…

…util.response/file-response.
  • Loading branch information...
1 parent 820e6dd commit 0949082935f758411f46ac4952979edfdeb2f29b @mmcgrana committed Mar 3, 2010
View
57 ring-core/src/ring/middleware/file.clj
@@ -1,51 +1,28 @@
(ns ring.middleware.file
"Static file serving."
(:use (clojure.contrib [def :only (defvar-)]
- [except :only (throw-if-not)])
- ring.util.response)
- (:require [ring.util.codec :as codec]
+ [except :only (throw-if-not)]))
+ (:require (ring.util [codec :as codec] [response :as response])
[clojure.contrib.java-utils :as ju])
(:import java.io.File))
-(defn- substring?
- "Returns true if sub is a substring of string."
- [sub #^String string]
- (.contains string sub))
-
(defn- ensure-dir
- "Ensures that a given directory exists, throwing if it does not."
- [dir]
- (let [fdir (ju/file dir)]
- (throw-if-not (.exists fdir) "Directory does not exist: %s" fdir)))
-
-(defvar- forbidden
- (-> (response "<html><body><h1>403 Forbidden</h1></body></html>")
- (status 403)
- (content-type "text/html")))
-
-(defn- maybe-file
- "Returns the File corresponding to the given relative path within the given
- dir if it exists, or nil if no such file exists."
- [dir path]
- (let [file (ju/file (str dir path))]
- (and (.exists file) (.canRead file) file)))
+ "Ensures that a directory exists at the given path, throwing if one does not."
+ [#^String dir-path]
+ (let [dir (File. dir-path)]
+ (throw-if-not (.exists dir) "Directory does not exist: %s" dir-path)))
(defn wrap-file
- "Wrap an app such that a given directory is checked for a static file
- with which to respond to the request, proxying the request to the
+ "Wrap an app such that the directory at the given root-path is checked for a
+ static file with which to respond to the request, proxying the request to the
wrapped app if such a file does not exist."
- [app dir]
- (ensure-dir dir)
+ [app #^String root-path]
+ (ensure-dir root-path)
(fn [req]
- (if (#{:get :head} (:request-method req))
- (let [uri (codec/url-decode (:uri req))]
- (if (substring? ".." uri)
- forbidden
- (let [path (cond
- (.endsWith "/" uri) (str uri "index.html")
- (re-find #"\.[a-z]+$" uri) uri
- :else (str uri ".html"))]
- (if-let [file (maybe-file dir path)]
- (response file)
- (app req)))))
- (app req))))
+ (if-not (= :get (:request-method req))
+ (app req)
+ (let [path (.substring (codec/url-decode (:uri req)) 1)]
+ (or
+ (response/file-response path
+ {:root root-path :index-files? true :html-files? true})
+ (app req))))))
View
29 ring-core/src/ring/util/response.clj
@@ -2,8 +2,6 @@
"Generate and augment Ring responses."
(:import java.io.File))
-; Ring responses
-
(defn redirect
"Returns a Ring response for an HTTP 302 redirect."
[url]
@@ -34,31 +32,28 @@
(.listFiles dir))))
(defn- get-file
- "Safely retrieve the correct file. See static-file for an
+ "Safely retrieve the correct file. See file-response for an
explanation of options."
[#^String path opts]
- (let [file (if-let [#^String root (:root opts)]
- (if (safe-path? root path)
- (File. root path))
- (File. path))]
- (if (.exists file)
- (if (.isDirectory file)
- (if (:index-files? opts true)
- (find-index-file file))
- file))))
+ (if-let [file (if-let [#^String root (:root opts)]
+ (and (safe-path? root path) (File. root path))
+ (File. path))]
+ (cond
+ (.isDirectory file)
+ (and (:index-files? opts true) (find-index-file file))
+ (.exists file)
+ file)))
-(defn static-file
- "Returns a Ring response to serve a static file, or nil if the file does
- not exist.
+(defn file-response
+ "Returns a Ring response to serve a static file, or nil if an appropriate
+ file does not exist.
Options:
:root - take the filepath relative to this root path
:index-files? - look for index.* files in directories, defaults to true"
[filepath & [opts]]
(if-let [file (get-file filepath opts)]
(response file)))
-; Ring response augmenters
-
(defn status
"Returns an updated Ring response with the given status."
[resp status]
View
25 ring-core/test/ring/middleware/file_test.clj
@@ -5,39 +5,32 @@
(deftest wrap-file-no-directory
(is (thrown-with-msg? Exception #".*Directory does not exist.*"
- (wrap-file (constantly :response) (File. "not_here")))))
+ (wrap-file (constantly :response) "not_here"))))
(def public-dir "test/ring/assets")
(def index-html (File. #^String public-dir "index.html"))
(def foo-html (File. #^String public-dir "foo.html"))
(def app (wrap-file (constantly :response) public-dir))
-(deftest wrap-file-unsafe-method
+(deftest test-wrap-file-unsafe-method
(is (= :response (app {:request-method :post :uri "/foo"}))))
-(deftest wrap-file-forbidden-url
- (let [{:keys [status body]} (app {:request-method :get :uri "/../foo"})]
- (is (= 403 status))
- (is (re-find #"Forbidden" body))))
+(deftest test-wrap-file-forbidden-url
+ (is (= :response (app {:request-method :get :uri "/../foo"}))))
-(deftest wrap-file-directory
+(deftest test-wrap-file-no-file
+ (is (= :response (app {:request-method :get :uri "/dynamic"}))))
+
+(deftest test-wrap-file-directory
(let [{:keys [status headers body]} (app {:request-method :get :uri "/"})]
(is (= 200 status))
(is (= {} headers))
(is (= index-html body))))
-(deftest wrap-file-sans-extension
- (let [{:keys [status headers body]} (app {:request-method :get :uri "/foo"})]
- (is (= 200 status))
- (is (= {} headers))
- (is (= foo-html body))))
-
-(deftest wrap-file-with-extension
+(deftest test-wrap-file-with-extension
(let [{:keys [status headers body]} (app {:request-method :get :uri "/foo.html"})]
(is (= 200 status))
(is (= {} headers))
(is (= foo-html body))))
-(deftest wrap-file-no-file
- (is (= :response (app {:request-method :get :uri "/dynamic"}))))
View
14 ring-core/test/ring/middleware/static_test.clj
@@ -3,17 +3,17 @@
ring.middleware.static)
(:import java.io.File))
-(def public-dir (File. "test/ring/assets"))
-(def foo-html (File. "test/ring/assets/foo.html"))
-(def nested-foo-html (File. "test/ring/assets/bars/foo.html"))
+(def public-dir "test/ring/assets")
+(def foo-html "test/ring/assets/foo.html")
+(def nested-foo-html "test/ring/assets/bars/foo.html")
(def statics ["/foo.html" "/bars/"])
(def app (wrap-static (constantly {:body :dynamic}) public-dir statics))
(defn app-response-body [uri]
(:body (app {:request-method :get :uri uri})))
-(deftest wrap-static-smoke
- (is (= foo-html (app-response-body "/foo.html")))
- (is (= nested-foo-html (app-response-body "/bars/foo.html")))
- (is (= :dynamic (app-response-body "/not/static"))))
+(deftest test-wrap-static-smoke
+ (is (= (File. foo-html) (app-response-body "/foo.html")))
+ (is (= (File. nested-foo-html) (app-response-body "/bars/foo.html")))
+ (is (= :dynamic (app-response-body "/not/static"))))
View
1 ring-core/test/ring/util/response_test.clj
@@ -5,3 +5,4 @@
(deftest test-redirect
(is (= {:status 302 :headers {"Location" "http://google.com"} :body ""}
(redirect "http://google.com"))))
+

0 comments on commit 0949082

Please sign in to comment.