Hi all! We're not using reitit at the moment (compojure), but I was wondering if reitit has the ability to specify that a path should be matched case insensitive? We have a server where some of the URLs are proxied to a different server, which unfortunately allows case insensitive URLs (up to a point). A few of those backend URLs we want to catch in our router and immediately return 403 (for example), but then we need to specify in our router as well that it is case insensitive...
good question: nothing built-in, but you could:
1. either write you routes all in lower-case or add a route compiler step to lower-case all routes behind the scenes
2. add a middleware outside of reitit to lower-case the :uri from request
@stefan.van.den.oord author replied above and you should take his word. but I was trying out how to do this. Note I'm newb so there should be more concise and correct ways to do this
(require '[reitit.core :as rc])
(require '[clojure.string :as str])
(def routes
[""
["route" :lowercase]
["Route" :uppercase]
["/abc"
["/Def" :abcdef]]])
(deftype CaseInsensitiveRouter [router]
rc/Router
(router-name [router] :case-insensitive-router)
(routes [this] (rc/routes router))
(compiled-routes [this] (rc/compiled-routes router))
(options [this] (rc/options router))
(route-names [this] (rc/route-names router))
(match-by-path [this path]
(let [routes (rc/routes router)
[p _] (first
(filter (fn [v]
(= (str/lower-case (first v)) (str/lower-case path))) routes))]
(tap> {:in :fn :p p :path path :routes routes})
(rc/match-by-path router p)))
(match-by-name [this name] (rc/match-by-name router name))
(match-by-name [this name path-params] (rc/match-by-name router name path-params)))
(def router1 (rc/router routes))
(rc/match-by-path router1 "route")
;; => #reitit.core.Match{:template "route", :data {:name :lowercase}, :result nil, :path-params {}, :path "route"}
(rc/match-by-path router1 "Route")
;; => #reitit.core.Match{:template "Route", :data {:name :uppercase}, :result nil, :path-params {}, :path "Route"}
(def router2 (CaseInsensitiveRouter. router1))
(rc/match-by-path router2 "route")
;; => #reitit.core.Match{:template "route", :data {:name :lowercase}, :result nil, :path-params {}, :path "route"}
(rc/match-by-path router2 "Route")
;; => #reitit.core.Match{:template "route", :data {:name :lowercase}, :result nil, :path-params {}, :path "route"}Thanks both of you! I decided to go for a middleware approach, that seems like a pretty good design and makes it also independent of the specific routing library that is used.