2011-10-11 25 views
27

我有一個名爲index.html的靜態文件,我想在有人請求/時提供。通常web服務器do this by default,但Compojure沒有。當有人要求/時,如何讓Compojure服務index.html在Compojure中默認使用index.html

下面是我使用的靜態目錄代碼:

; match anything in the static dir at resources/public 
(route/resources "/") 

回答

20

這將是一個非常簡單的環中間件:

(defn wrap-dir-index [handler] 
    (fn [req] 
    (handler 
    (update-in req [:uri] 
       #(if (= "/" %) "/index.html" %))))) 

就具有這種功能包裝你的路線,並請求/在您的其他代碼看到它們之前轉化爲請求/index.html

(def app (-> (routes (your-dynamic-routes) 
        (resources "/")) 
      (...other wrappers...) 
      (wrap-dir-index))) 
+3

我想我的觀點是:Compojure沒有這樣做,因爲用Ring來代替它很容易。您的Clojure Web堆棧不是一個全面的平臺,而是一系列可插拔和專用的工具。用專爲它設計的工具解決問題X. – amalloy

38

另一種方法是在附加路由中創建重定向或直接響應。像這樣:

(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")) 

「/」路徑返回公用文件夾中存在的「index.html」文件響應。 「/ a」路徑直接通過「內聯」文件index.html進行響應。

更多關於環響應:https://github.com/mmcgrana/ring/wiki/Creating-responses

編輯:去除不需要[ring.adapter.jetty]導入。

+5

嗨。 (GET「/」[](resp/resource-response「index.html」{:root「public」}))對我來說非常合適。 – joshua

+0

小心不要提供您想要的內容類型。另一箇中間件如'wrap-content-type'可能會破壞你的代碼。我發佈了[答案](http://stackoverflow.com/a/32491623/1707589)解決這個問題。 – fasfsfgs

3

最近我發現,當Clojure/Compojure應用程序在Jetty或Tomcat下作爲.war運行時,@ amalloy的答案不起作用。在這種情況下,需要更新:path-info。另外,我認爲這個版本可以處理任何路線,而不僅僅是「根」路線。

(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))))) 

參見:https://groups.google.com/forum/#!msg/compojure/yzvpQVeQS3w/RNFkFJaAaYIJ

更新:替換,例如與工作的版本。

25
(ns compj-test.core 
    (:use [compojure.core]) 
    (:require 
     [ring.util.response :as resp])) 

(defroutes main-routes 
    (GET "/" [] (resp/redirect "/index.html"))) 

你要求的是從/到/index.html的重定向。其簡單如(resp /重定向目標)。無需過度複雜的事情。

+2

這是最直接和最合理的迴應,謝謝! – scape

+1

是的,這是唯一一個爲我工作的人 – Zubair

18

這工作得很好。無需編寫一個環形中間件。

(:require [clojure.java.io :as io]) 

(defroutes app-routes 
(GET "/" [] (io/resource "public/index.html"))) 
+0

不知道它是否回答了這個問題,但它幫助我獲得了我需要的東西! Upvoted!謝謝! – leontalbot

+0

小心不要提供您想要的內容類型。另一箇中間件如'wrap-content-type'可能會破壞你的代碼。我發佈了[答案](http://stackoverflow.com/a/32491623/1707589)解決這個問題。 – fasfsfgs

0

只是一個考慮Binita,一直困擾我一直在經歷。儘管我無法找到有關訂單定義的Compojure路線我發現這行不通

(GET "/*" [] r/static) 
(GET "/" [] (clojure.java.io/resource "public/index.html")) 

,而這確實工作

(GET "/" [] (clojure.java.io/resource "public/index.html")) 
(GET "/*" [] r/static) 

顯然*配襯也爲空字符串的重要性,任何文件但我認爲這個命令根本不重要。

+0

小心不要提供你想要的內容類型。另一箇中間件如'wrap-content-type'可能會破壞你的代碼。我發佈了[答案](http://stackoverflow.com/a/32491623/1707589)解決這個問題。 – fasfsfgs

1

當其他代碼不起作用時, 請嘗試此代碼。

(GET "/about/" [] (ring.util.response/content-type 
        (ring.util.response/resource-response "about/index.html" {:root "public"}) "text/html")) 
+2

請爲您的答案添加一些解釋,以使其對其他讀者更有用。 –

+0

很好的答案。它使用環提供的解決方案提供指定其內容類型的資源。 – fasfsfgs

7

在這裏觀看了很多的答案後,我用下面的代碼:

(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")))) 
  • 沒有重定向頁面;
  • 不需要另一箇中間件;
  • index.html停留在正確的文件夾(resources/public/index.html);
  • 它可以與其他中間件一起工作(當使用某些鈴聲默認中間件時,很多答案都會中斷);
  • 它提供了內容類型,因此它可以與wrap-content-type中間件一起使用。

檢查ring-defaults。它具有您應該在您的項目中使用的最佳實踐中間件。

+0

獲取表單缺少空參數[],否則這正是我所需要的,謝謝! – hequ

+0

@hequ謝謝!用缺少的括號更新答案。 – fasfsfgs

+0

不應該'resp/content-type'被包裝在一個表單中? –