I have a static file called index.html
that I开发者_StackOverflow'd like to serve when someone requests /
. Usually web servers do this by default, but Compojure doesn't. How can I make Compojure serve index.html
when someone requests /
?
Here's the code I'm using for the static directory:
; match anything in the static dir at resources/public
(route/resources "/")
An alternative could be to create either a redirect or a direct response in an additional route. Like so:
(ns compj-test.core
(:use [compojure.core])
(:require [compojure.route :as route]
[ring.util.response :as resp]))
(defroutes main-routes
(GET "/" [] (resp/file-response "index.html" {:root "public"}))
(GET "/a" [] (resp/resource-response "index.html" {:root "public"}))
(route/resources "/")
(route/not-found "Page not found"))
The "/" route returns a file response of "index.html" which is present in the public folder. The "/a" route responds directly by 'inlineing' the file index.html.
More on ring responses: https://github.com/mmcgrana/ring/wiki/Creating-responses
EDIT: removed unnecessary [ring.adapter.jetty]
import.
(ns compj-test.core
(:use [compojure.core])
(:require
[ring.util.response :as resp]))
(defroutes main-routes
(GET "/" [] (resp/redirect "/index.html")))
What you're asking for is a redirect from / to /index.html. Its as simple as (resp/redirect target). No need to over complicate things.
This would be a pretty simple Ring middleware:
(defn wrap-dir-index [handler]
(fn [req]
(handler
(update-in req [:uri]
#(if (= "/" %) "/index.html" %)))))
Just wrap your routes with this function, and requests for /
get transformed into requests for /index.html
before the rest of your code sees them.
(def app (-> (routes (your-dynamic-routes)
(resources "/"))
(...other wrappers...)
(wrap-dir-index)))
This works just fine. No need to write a ring middle-ware.
(:require [clojure.java.io :as io])
(defroutes app-routes
(GET "/" [] (io/resource "public/index.html")))
After viewing a lot of the answers here, I'm using the following code:
(ns app.routes
(:require [compojure.core :refer [defroutes GET]]
[ring.util.response :as resp]))
(defroutes appRoutes
;; ...
;; your routes
;; ...
(GET "/" []
(resp/content-type (resp/resource-response "index.html" {:root "public"}) "text/html"))))
- No redirects;
- No need of another middleware;
- index.html stays in the right folder (resources/public/index.html);
- It works with other middleware (a lot of the answers break when using with some ring default middleware);
- It provides content-type so it works with wrap-content-type middleware.
Check ring-defaults. It has best practices middleware you should use on your projects.
Recently I discovered that @amalloy's answer doesn't work when the Clojure/Compojure app is run under Jetty or Tomcat as a .war. In this case :path-info
needs to be updated. Also, I think this version will handle any route, not just the "root" route.
(defn- wrap-dir-index [handler]
(fn [request]
(handler
(let [k (if (contains? request :path-info) :path-info :uri) v (get request k)]
(if (re-find #"/$" v)
(assoc request k (format "%sindex.html" v))
request)))))
See also: https://groups.google.com/forum/#!msg/compojure/yzvpQVeQS3w/RNFkFJaAaYIJ
UPDATED: Replaced example with a version that works.
when other code doesnt work, try this code.
(GET "/about/" [] (ring.util.response/content-type
(ring.util.response/resource-response "about/index.html" {:root "public"}) "text/html"))
Just a consideration Binita, a gotcha I have been experiencing. Despite I couldn't find any documentation regarding importance of order defining Compojure routes I find out that this doesn't work
(GET "/*" [] r/static)
(GET "/" [] (clojure.java.io/resource "public/index.html"))
while this does work
(GET "/" [] (clojure.java.io/resource "public/index.html"))
(GET "/*" [] r/static)
Obviously the *
matchs also the empty string but I thought that the order shouldn't matter at all.
精彩评论