2015-06-07 46 views
4

我剛剛嘗試添加這個包裝(-> routes (wrap-ssl-redirect))用於將http自動重定向到https,但是當我部署到heroku時,https://在我的瀏覽器中未變綠,並且網站無法加載。Clojure:在heroku上wrap-ssl-redirect?

是不是默認的heroku端口443,這也應該是默認的wrap-ssl-redirect函數?

出了什麼問題?

謝謝!

編輯:

我的代碼:

(defn prod-app [routes] 
    (-> routes 
     (wrap-keyword-params) 
     (wrap-params) 
     (wrap-ssl-redirect))) 

(defn -main [] 
    (let [port (Integer/parseInt (get (System/getenv) "PORT" "5000"))] 
    (jetty/run-jetty (prod-app domain-specific-routes) 
        {:port port :join? false}))) 

編輯2:

我剛剛發現這個線程可能解決我的問題:Clojure/Noir: Force HTTPS, redirect if the request was http:// to https://

想出了這個require-https處理器FN :

(defn https-url [request-url] 
    (str "https://" 
     (:server-name request-url) 
     ":" 
     (:server-port request-url) 
     (:uri request-url))) 

(defn require-https 
    [handler] 
    (fn [request] 
    (if (and (= (:scheme request) :http) 
      (= (get-in request [:headers "host"]) "secure.mydomain.com")) 
     (ring.util.response/redirect (https-url request)) 
     (handler request)))) 

但是,當我嘗試連接到http://secure.mydomain.com,我在瀏覽器地址欄https://secure.mydomain.com:80/ seing一個端口,並得到這個消息ERR_SSL_PROTOCOL_ERROR

+0

您需要在Heroku上正常綁定到端口環境變量。你的日誌顯示任何消息? –

+0

我在日誌中沒有看到任何問題。現在,如果我嘗試使用'( - > routes(wrap-ssl-redirect {:ssl-port(Integer/parseInt(get(System/getenv)「PORT」「5000」))}' 'status = 301'並且瀏覽器在我的域名旁邊顯示一個5位數的端口在我的heroku配置中,我沒有'PORT'變種 – leontalbot

+0

你可以用有問題的日誌更新你的問題,複製你正在追蹤的步驟,以及過去在Heroku上爲你工作的步驟? –

回答

0

萬歲lib-noir及其wrap-force-ssl FN。

我只是需要改變它以適應我的需求(我有一個SSL證書。因爲即使我的Clojure應用程序處理一個以上的域的一個子域)

這裏是我的FN:

(defn wrap-force-ssl 
    "Almost like in lib-noir. 
    If the request's scheme is not https [and is for 'secure.'], redirect with https. 
    Also checks the X-Forwarded-Proto header." 
    [app] 
    (fn [req] 
    (let [headers (:headers req) 
      host (headers "host")] 
     (if (or (= :https (:scheme req)) 
       (= "https" (headers "x-forwarded-proto")) 
       (not= "secure.mydomain.com" host)) ;you might not need this! 
     (app req) 
     (noir.response/redirect (str "https://" host (:uri req)) :permanent))))) 

感謝Chris格蘭傑和朋友!

+1

謝謝!這真的很有用。一個想法是,可能要考慮在請求中檢查':query-string'並將其添加到重定向位置。 – adamneilson

+0

@adamneilson你可以提供一個例子或者建議編輯嗎? (noir.response/redirect(if(nil?(:query-string req)) (格式爲「https://%s%s」host(:uri req) – leontalbot

+1

我在想: ' )) (格式爲「https://%s%s?%s」host(:uri req)(:query-string req))):permanent)' – adamneilson

2

在Heroku上,你需要bind to the port他們給你一個環境變量。 Heroku還將負載平衡器放在您的應用程序前面。他們將終止SSL連接並通過HTTP與您的應用程序進行通信,因此您的應用程序將看到的方案始終爲HTTP。標準wrap-ssl-redirect在這種情況下效果不好,我認爲它不會成功重定向(即使用戶重定向到HTTPS,用戶仍然可以通過HTTP進行連接)。

但Heroku將x-forwarded-proto添加到每個請求的頭部以解決此問題,因此您可以查看您的客戶端正在使用哪種協議。在同一個ring.middleware.ssl命名空間中是一個wrap-forwarded-scheme中間件。

「中間件改變所述:所述請求的地圖的方案來在一個請求頭本 值如果應用程序位於後面處理該SSL傳輸一個 反向代理或負載平衡器,這是有用 的標題默認爲x-forwarded-proto。「

如果您首先將您的路線包裹起來,然後用wrap-ssl-redirect包裹您的路線,那麼它應該正確重定向到HTTPS。您還可以添加ring.middleware.ssl/wrap-hsts執行HSTS還有:

(wrap-forwarded-scheme (wrap-ssl-redirect (wrap-hsts app))) 
+1

hmm ..添加'wrap-forwarded-scheme'使chrome說:'ERR_TOO_MANY_REDIRECTS'。Heroku日誌看起來像這樣:'at = info method = GET path =「/ favicon.ico」host = www.mydomain.com request_id = 0e85ea4c-044c-4bf4-a16b-fe729aabad3b fwd =「77.74.193.277」dyno = web.1 connect = 0ms service = 72ms status = 301 bytes = 170' – leontalbot

+1

也許考慮在GitHub項目上打開一個問題,詢問如何使用Heroku的文檔,他們可能是最好的人。 –

+0

沒有工作。我打開了一張票,但遺憾的是Heroku能找到答案。它發生了...... – leontalbot