diff --git a/modules/reitit-ring/src/reitit/ring.cljc b/modules/reitit-ring/src/reitit/ring.cljc index 933ba065..397eb25b 100644 --- a/modules/reitit-ring/src/reitit/ring.cljc +++ b/modules/reitit-ring/src/reitit/ring.cljc @@ -110,6 +110,35 @@ (respond nil)))] (f handlers)))))) +(defn redirect-trailing-slash-handler + "A ring handler that redirects a missing path if there is an + existing path that only differs in the ending slash. + + | key | description | + |---------|-------------| + | :method | :add - redirects slash-less to slashed | + | | :strip - redirects slashed to slash-less | + | | :both - works both ways (default) | + " + [{:keys [method] :or {method :both}}] + (let [redirect-handler (fn redirect-handler [request] + (let [uri (:uri request) + maybe-redirect (fn maybe-redirect [path] + (if (r/match-by-path (::r/router request) path) + {:status 308 ; permanent redirect + :headers {"Location" path} + :body ""}))] + (if (str/ends-with? uri "/") + (if (not= method :add) + (maybe-redirect (subs uri 0 (-> uri count dec)))) + (if (not= method :strip) + (maybe-redirect (str uri "/"))))))] + (fn + ([request] + (redirect-handler request)) + ([request respond _] + (respond (redirect-handler request)))))) + (defn create-default-handler "A default ring handler that can handle the following cases, configured via options: