2015-06-07 44 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