From 0b711b256004cb43ba84728d2cb934397395a1ef Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Sun, 29 Apr 2018 16:49:05 +0300 Subject: [PATCH] Support `:index-files` in create-resource-handler --- dev-resources/public/docs/index.html | 1 + doc/ring/static.md | 3 ++- examples/ring-swagger/README.md | 2 +- modules/reitit-ring/src/reitit/ring.cljc | 27 +++++++++++++++++------- test/cljc/reitit/ring_test.cljc | 6 ++++++ 5 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 dev-resources/public/docs/index.html diff --git a/dev-resources/public/docs/index.html b/dev-resources/public/docs/index.html new file mode 100644 index 00000000..6e7c1e6a --- /dev/null +++ b/dev-resources/public/docs/index.html @@ -0,0 +1 @@ +

hello

diff --git a/doc/ring/static.md b/doc/ring/static.md index 8abe79c0..959b4746 100644 --- a/doc/ring/static.md +++ b/doc/ring/static.md @@ -54,10 +54,11 @@ A better way to serve files from conflicting paths, e.g. `"/*"`, is to serve the | :root | optional resource root, defaults to `"public"` | :path | optional path to mount the handler to. Works only if mounted outside of a router. | :loader | optional class loader to resolve the resources +| :index-files | optional vector of index-files to look in a resource directory, defaults to `["index.html"]` | :allow-symlinks? | allow symlinks that lead to paths outside the root classpath directories, defaults to `false` ### TODO -* support for things like `:cache`, `:etag`, `:last-modified?`, `:index-files` and `:gzip` +* support for things like `:cache`, `:etag`, `:last-modified?`, and `:gzip` * support for ClojureScript * serve from file-system diff --git a/examples/ring-swagger/README.md b/examples/ring-swagger/README.md index 9d37aaff..79416373 100644 --- a/examples/ring-swagger/README.md +++ b/examples/ring-swagger/README.md @@ -17,7 +17,7 @@ http GET :3000/api/swagger.json ``` * swagger.json: http://localhost:3000/api/swagger.json -* swagger-ui: http://localhost:3000/api-docs/index.html +* swagger-ui: http://localhost:3000/api-docs/ diff --git a/modules/reitit-ring/src/reitit/ring.cljc b/modules/reitit-ring/src/reitit/ring.cljc index 62cde8b4..2fd09a98 100644 --- a/modules/reitit-ring/src/reitit/ring.cljc +++ b/modules/reitit-ring/src/reitit/ring.cljc @@ -68,6 +68,7 @@ (respond (not-found request))))))) #?(:clj + ;; TODO: optimize for perf (defn create-resource-handler "A ring handler for serving classpath resources, configured via options: @@ -77,29 +78,39 @@ | :root | optional resource root, defaults to `\"public\"` | :path | optional path to mount the handler to. Works only if mounted outside of a router. | :loader | optional class loader to resolve the resources + | :index-files | optional vector of index-files to look in a resource directory, defaults to `[\"index.html\"]` | :allow-symlinks? | allow symlinks that lead to paths outside the root classpath directories, defaults to `false`" ([] (create-resource-handler nil)) - ([{:keys [parameter root path loader allow-symlinks?] + ([{:keys [parameter root path loader allow-symlinks? index-files] :or {parameter (keyword "") - root "public"}}] + root "public" + index-files ["index.html"]}}] (let [options {:root root, :loader loader, :allow-symlinks? allow-symlinks?} path-size (count path) create (fn [handler] (fn ([request] (handler request)) ([request respond _] (respond (handler request))))) - response (fn [path] - (if-let [response (response/resource-response path options)] - (response/content-type response (mime-type/ext-mime-type path)))) + resource-response (fn [path accept] + (if-let [path (accept path)] + (if-let [response (response/resource-response path options)] + (response/content-type response (mime-type/ext-mime-type path))))) + path-or-index-response (fn [path accept] + (or (resource-response path accept) + (loop [[file & files] index-files] + (if file + (or (resource-response (str path "/" file) accept) + (recur files)))))) handler (if path (fn [request] (let [uri (:uri request)] - (if (>= (count uri) path-size) - (response (subs uri path-size))))) + (path-or-index-response uri (fn [path] + (if (>= (count path) path-size) + (subs path path-size)))))) (fn [request] (let [path (-> request :path-params parameter)] - (or (response path) {:status 404}))))] + (or (path-or-index-response path identity) {:status 404}))))] (create handler))))) (defn ring-handler diff --git a/test/cljc/reitit/ring_test.cljc b/test/cljc/reitit/ring_test.cljc index 8ef1bc9a..eb7d265c 100644 --- a/test/cljc/reitit/ring_test.cljc +++ b/test/cljc/reitit/ring_test.cljc @@ -293,6 +293,12 @@ (is (get-in response [:headers "Last-Modified"])) (is (= "file\n" (slurp (:body response)))))) + (testing "index-files" + (let [response (app {:uri "/files/docs", :request-method :get})] + (is (= "text/html" (get-in response [:headers "Content-Type"]))) + (is (get-in response [:headers "Last-Modified"])) + (is (= "

hello

\n" (slurp (:body response)))))) + (testing "not found" (let [response (app {:uri "/files/not-found", :request-method :get})] (is (= 404 (:status response)))))