Clojure:heroku 上的 wrap-ssl-redirect?

leo*_*bot 5 https clojure ring

我刚刚尝试添加此包装器(-> routes (wrap-ssl-redirect))以将 http 自动重定向到 https,但是当我部署到 heroku 时,https://浏览器中没有显示绿色,网站也没有加载。

不是默认的 heroku port 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})))
Run Code Online (Sandbox Code Playgroud)

编辑2:

我刚刚找到了可以解决我的问题的线程:Clojure / Noir: Force HTTPS, 如果请求是 http:// 到 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))))
Run Code Online (Sandbox Code Playgroud)

但是当我尝试连接时http://secure.mydomain.com,我在浏览器地址栏中看到一个端口https://secure.mydomain.com:80/并收到此消息ERR_SSL_PROTOCOL_ERROR

Dan*_*ton 4

在 Heroku 上,您需要通过环境变量绑定到他们为您提供的端口。Heroku 还在您的应用程序前面放置了负载均衡器。它们将终止 SSL 连接并通过 HTTP 与您的应用程序通信,因此您的应用程序将看到的方案将始终是 HTTP。标准wrap-ssl-redirect在这种情况下不能很好地工作,我认为它永远不会成功重定向(它会认为用户正在通过 HTTP 连接,即使他们确实被重定向到 HTTPS)。

然而,Heroku 添加x-forwarded-proto到每个请求的标头来解决这个问题,这样您就可以看到您的客户端正在使用哪个协议。在同一个ring.middleware.ssl命名空间中有一个wrap-forwarded-scheme中间件。

“将请求映射的 :scheme 更改为请求标头中存在的值的中间件。如果您的应用程序位于处理 SSL 传输的反向代理或负载均衡器后面,这非常有用。标头默认为 x-forwarded-proto。 ”

如果你先用这个包装你的路由,然后用wrap-ssl-redirect,它应该正确重定向到 HTTPS。您还可以添加ring.middleware.ssl/wrap-hsts以强制执行HSTS

(wrap-forwarded-scheme (wrap-ssl-redirect (wrap-hsts app)))
Run Code Online (Sandbox Code Playgroud)