用于匹配尾部斜杠的 Compojure 正则表达式

发布于 2024-12-19 18:05:34 字数 676 浏览 4 评论 0原文

也许我只是个白痴,但我无法在 Clojure 中为可选的尾部斜杠设置匹配。

lein repl
REPL started; server listening on localhost port 47383
user=> (use 'ring.mock.request 'clout.core)
nil
user=> (route-matches "/article/" (request :get "/article/"))
{}
user=> (route-matches "/article/?" (request :get "/article"))
nil
user=> (route-matches "/article/?" (request :get "/article/"))
nil
user=> (route-matches #"/article/?" (request :get "/article/"))
java.lang.IllegalArgumentException: No implementation of method: :route-matches of protocol: #'clout.core/Route found for class: java.util.regex.Pattern (NO_SOURCE_FILE:0)

我可以使用什么正则表达式来匹配 Compojure 中的可选尾部斜杠?

Maybe I'm just an idiot, but I can't set up a match for an optional trailing slash in Clojure.

lein repl
REPL started; server listening on localhost port 47383
user=> (use 'ring.mock.request 'clout.core)
nil
user=> (route-matches "/article/" (request :get "/article/"))
{}
user=> (route-matches "/article/?" (request :get "/article"))
nil
user=> (route-matches "/article/?" (request :get "/article/"))
nil
user=> (route-matches #"/article/?" (request :get "/article/"))
java.lang.IllegalArgumentException: No implementation of method: :route-matches of protocol: #'clout.core/Route found for class: java.util.regex.Pattern (NO_SOURCE_FILE:0)

What regex can I use to match an optional trailing slash in Compojure?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

魔法唧唧 2024-12-26 18:05:34

clout 期望作为 route-matches 的第一个参数的路径字符串不是正则表达式,而是可以包含关键字和 * 的字符串通配符。

我相信 clout 本身并不支持定义忽略尾部斜杠的路由。您可以使用删除尾部斜杠的中间件函数来解决该问题。以下函数取自旧版本的compojure源代码(在大重构之前),我无法确定它们是否移动到了新的地方。这是引入这些函数的原始提交

(defn with-uri-rewrite
  "Rewrites a request uri with the result of calling f with the
   request's original uri.  If f returns nil the handler is not called."
  [handler f]
  (fn [request]
    (let [uri (:uri request)
          rewrite (f uri)]
      (if rewrite
        (handler (assoc request :uri rewrite))
        nil))))

(defn- uri-snip-slash
  "Removes a trailing slash from all uris except \"/\"."
  [uri]
  (if (and (not (= "/" uri))
           (.endsWith uri "/"))
    (chop uri)
    uri))

(defn ignore-trailing-slash
  "Makes routes match regardless of whether or not a uri ends in a slash."
  [handler]
  (with-uri-rewrite handler uri-snip-slash))

The path string expected by clout as the first argument to route-matches is not a regex, but a string that can contain keywords and the * wildcard.

I believe clout doesn't natively support defining routes that ignore a trailing slash. You could solve the problem with a middleware function that removes trailing slashes. The following functions were taken from an old version of the compojure source code (before the big refactoring), I couldn't find out if they moved to a new place. Here is the original commit that introduced these functions.

(defn with-uri-rewrite
  "Rewrites a request uri with the result of calling f with the
   request's original uri.  If f returns nil the handler is not called."
  [handler f]
  (fn [request]
    (let [uri (:uri request)
          rewrite (f uri)]
      (if rewrite
        (handler (assoc request :uri rewrite))
        nil))))

(defn- uri-snip-slash
  "Removes a trailing slash from all uris except \"/\"."
  [uri]
  (if (and (not (= "/" uri))
           (.endsWith uri "/"))
    (chop uri)
    uri))

(defn ignore-trailing-slash
  "Makes routes match regardless of whether or not a uri ends in a slash."
  [handler]
  (with-uri-rewrite handler uri-snip-slash))
月下凄凉 2024-12-26 18:05:34

这是没有依赖项的中间件的精简版本:

(defn with-ignore-trailing-slash [handler] (fn [request]
  (let [uri       (request :uri)
        clean-uri (if (and (not= "/" uri) (.endsWith uri "/"))
                    (subs uri 0 (- (count uri) 1))
                    uri)]
    (handler (assoc request :uri clean-uri)))))

欢迎错误修复编辑。

Here's a condensed version of the middleware with no dependencies:

(defn with-ignore-trailing-slash [handler] (fn [request]
  (let [uri       (request :uri)
        clean-uri (if (and (not= "/" uri) (.endsWith uri "/"))
                    (subs uri 0 (- (count uri) 1))
                    uri)]
    (handler (assoc request :uri clean-uri)))))

Bug fix edits welcome.

私野 2024-12-26 18:05:34

对于那些寻找压缩解决方案的人:)

(defn- with-ignore-trailing-slash [handler]
  (fn [request]
    (let [uri (request :uri)
          clean-uri (str/replace uri #"^(.+?)/+$" "$1")]
      (handler (assoc request :uri clean-uri)))))

For those looking for an even more compressed solution :)

(defn- with-ignore-trailing-slash [handler]
  (fn [request]
    (let [uri (request :uri)
          clean-uri (str/replace uri #"^(.+?)/+$" "$1")]
      (handler (assoc request :uri clean-uri)))))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文