我试图使用Ring路由实现的行为大致在this question中描述。
基本上我有一些以尾部斜杠结尾的网址,而且我正在尝试创建一个中间件,当{并且仅当example.com/foo
是example.com/foo/
时才会从/foo/
重定向到/foo
有效的网址和(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))))))
不是。
我目前正在使用这个中间件
/foo
几乎应有的一切:它从/foo/
重定向到/foo/
iff /foo
存在而(handler req)
不存在。
我担心的是,此解决方案将至少两次调用/foo
- 一次请求(:body request)
,并在客户端请求重定向的网址时再次调用{{1}}。现在这不是一个问题,但我可以想象,对于一些有数百个数据库查询或某些此类事情的慢速页面的响应时间加倍是很痛苦的。
有没有办法简单地检查给定URL是否存在处理程序,而不调用该处理程序?我们可以完全避免这个问题,让{{1}}懒惰吗?
答案 0 :(得分:2)
在戒指中没有通用的方法来检查“这是一个有效的uri吗?”没有用uri调用整个堆栈处理程序,因为没有uris的中央列表,但即使这样,处理程序也可以拒绝处理任何原因的请求,而不仅仅是基于它的uri。
我可能会走另一条路;对于实际需要此行为的所有处理程序,使它们也捕获“未删除”的版本,然后在需要/有用时重定向。
或者使用单独的处理程序/中间件,如果url应该总是以斜线结束给定一些规则,并且如果不匹配则让重定向失败。无论哪种方式,最终用户都会得到404,所以谁在乎,真的吗?
但是最具体的处理程序通常最适合做出决定。
哦,你可能不只是将POST转发给其他URI。
答案 1 :(得分:0)
我修改了你的代码。
(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 (-> req
(assoc :uri added-slash)
(assoc :path-info added-slash))))
(redirect added-slash)
resp))))))
您需要更改:path-info。