I've just tried add this wrapper (-> routes (wrap-ssl-redirect))
for auto redirecting http to https, but when I deploy to heroku, the https://
doesn't get green in my browser, and the website doesn't load.
Isn't the default heroku port 443
, which should also be the default from wrap-ssl-redirect
function?
What is wrong?
Thank you!
EDIT:
My code:
(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})))
EDIT 2:
I just found this thread which could solve my problem: Clojure / Noir: Force HTTPS, redirect if the request was http:// to https://
Came up with this require-https
handler 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))))
But when I try to connect to http://secure.mydomain.com
, I am seing a port in the browser address bar https://secure.mydomain.com:80/
and got this message ERR_SSL_PROTOCOL_ERROR
.
On Heroku, you need to bind to the port they give you through an environment variable. Heroku also sit load balancers in front of your app. They will terminate the SSL connection and communicate with your app over HTTP, so the scheme that your app will see will always be HTTP. The standard wrap-ssl-redirect
won't work well with this scenario, I don't think it will ever successfully redirect (it would think the user is connecting over HTTP even if they did get redirected to HTTPS).
However Heroku adds x-forwarded-proto
to the headers of every request to work around this, so you can see which protocol your client is using. In the same ring.middleware.ssl
namespace is a wrap-forwarded-scheme
middleware.
"Middleware that changes the :scheme of the request map to the value present in a request header. This is useful if your application sits behind a reverse proxy or load balancer that handles the SSL transport. The header defaults to x-forwarded-proto."
If you wrap your routes with this first, then with wrap-ssl-redirect
, that it should redirect to HTTPS correctly. You can also add ring.middleware.ssl/wrap-hsts
to enforce HSTS as well:
(wrap-forwarded-scheme (wrap-ssl-redirect (wrap-hsts app)))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With