The behavior I'm trying to implement using Ring routes is approximately described in this question.
Basically I have some URLs that end with trailing slashes, and I'm trying to create a middleware that will redirect from e.g example.com/foo
to example.com/foo/
if and only if /foo/
is a valid URL and /foo
is not.
I'm currently using this middleware
(defn good-response? [resp]
(and resp (not= (:status resp) 404)))
(defn wrap-slash [handler]
(fn [{:keys [uri] :as req}]
(let [resp (handler req)]
(if (or (good-response? resp) (.endsWith "/" uri))
resp
(let [added-slash (str uri "/")]
(if (good-response? (handler (assoc req :uri added-slash)))
(redirect added-slash)
resp))))))
Which does almost everything it should: It redirects from /foo
to /foo/
iff /foo/
exists and /foo
does not.
My concern is that this solution will call (handler req)
at least twice - once on the request for /foo
and again when the client requests the redirected URL. It's not a problem now, but I could imagine it being painful to double the response time for some slow page with hundreds of DB queries or some such thing.
Is there a way to simply check if a handler exists for a given URL, without calling that handler? Could we avoid the problem entirely by say, making (:body request)
lazy?