Middleware for redirecting users to HTTPS sessions

(ns metabase.server.middleware.ssl
  (:require
   [clojure.string :as str]
   [metabase.public-settings :as public-settings]
   [metabase.request.core :as request]
   [ring.util.request :as req]
   [ring.util.response :as response]))
(set! *warn-on-reflection* true)

The set of URLs that should not be forced to redirect to their HTTPS equivalents

(def no-redirect-https-uris
  #{"/api/health"})
(defn- get-request? [{method :request-method}]
  (or (= method :head)
      (= method :get)))
(defn- https-url [url-string]
  (let [url (java.net.URL. url-string)
        site-url (java.net.URL. (public-settings/site-url))]
    (str (java.net.URL. "https" (.getHost site-url) (.getPort site-url) (.getFile url)))))

Given a HTTP request, return a redirect response to the equivalent HTTPS URL.

(defn- ssl-redirect-response
  [request]
  (-> (response/redirect (https-url (req/request-url request)))
      (response/status   (if (get-request? request) 301 307))))

Redirect users to HTTPS sessions when certain conditions are met. See no-redirect-https-uris for URIs excluded from https redirects.

(defn redirect-to-https-middleware
  [handler]
  (fn [request respond raise]
    (cond
      (str/blank? (public-settings/site-url))
      (handler request respond raise)
      (not (str/starts-with? (public-settings/site-url) "https:"))
      (handler request respond raise)
      (no-redirect-https-uris (:uri request))
      (handler request respond raise)
      (and
       (public-settings/redirect-all-requests-to-https)
       (not (request/https? request)))
      (respond (ssl-redirect-response request))
      :else (handler request respond raise))))