mirror of
https://github.com/metosin/reitit.git
synced 2025-12-24 02:48:25 +00:00
Implement trailing slash handler as custom Router
This commit is contained in:
parent
54a26aded7
commit
5ab3e26f16
2 changed files with 55 additions and 33 deletions
|
|
@ -15,21 +15,37 @@
|
|||
(map (juxt keyword #(.get q %)))
|
||||
(into {}))))
|
||||
|
||||
(defn trailing-slash-router [parent method]
|
||||
(if method
|
||||
^{:type ::r/router}
|
||||
(reify r/Router
|
||||
(router-name [_]
|
||||
:trailing-slash-handler)
|
||||
(routes [_]
|
||||
(r/routes parent))
|
||||
(compiled-routes [_]
|
||||
(r/compiled-routes parent))
|
||||
(options [_]
|
||||
(r/options parent))
|
||||
(route-names [_]
|
||||
(r/route-names parent))
|
||||
(match-by-path [_ path]
|
||||
(or (r/match-by-path parent path)
|
||||
(if (str/ends-with? path "/")
|
||||
(if (not= method :add)
|
||||
(r/match-by-path parent (subs path 0 (dec (count path)))))
|
||||
(if (not= method :remove)
|
||||
(r/match-by-path parent (str path "/"))))))
|
||||
(match-by-name [_ name]
|
||||
(r/match-by-name parent name)))
|
||||
parent))
|
||||
|
||||
(defn match-by-path
|
||||
"Given routing tree and current path, return match with possibly
|
||||
coerced parameters. Returns nil if no match found."
|
||||
[router path]
|
||||
(let [uri (.parse Uri path)
|
||||
path (.getPath uri)]
|
||||
(if-let [match (or (r/match-by-path router path)
|
||||
(if-let [trailing-slash-handling (:trailing-slash-handling (r/options router))]
|
||||
;; TODO: Maybe the original path should be added under some key in match,
|
||||
;; so it is easy for user to see if trailing slash "redirect" happened?
|
||||
(if (str/ends-with? path "/")
|
||||
(if (not= trailing-slash-handling :add)
|
||||
(r/match-by-path router (subs path 0 (dec (count path)))))
|
||||
(if (not= trailing-slash-handling :remove)
|
||||
(r/match-by-path router (str path "/"))))))]
|
||||
(let [uri (.parse Uri path)]
|
||||
(if-let [match (r/match-by-path router (.getPath uri))]
|
||||
;; User can update browser location in on-navigate call using replace-state
|
||||
(let [q (query-params uri)
|
||||
match (assoc match :query-params q)
|
||||
|
|
@ -62,7 +78,8 @@
|
|||
([raw-routes]
|
||||
(router raw-routes {}))
|
||||
([raw-routes opts]
|
||||
(r/router raw-routes (merge {:compile rc/compile-request-coercers} opts))))
|
||||
(-> (r/router raw-routes (merge {:compile rc/compile-request-coercers} opts))
|
||||
(trailing-slash-router (:trailing-slash-handling opts)))))
|
||||
|
||||
(defn match-by-name!
|
||||
"Logs problems using console.warn"
|
||||
|
|
|
|||
|
|
@ -12,10 +12,11 @@
|
|||
|
||||
(deftest match-by-path-test
|
||||
(testing "simple"
|
||||
(let [router (r/router ["/"
|
||||
["" ::frontpage]
|
||||
["foo" ::foo]
|
||||
["bar" ::bar]])]
|
||||
(let [router (rf/router
|
||||
["/"
|
||||
["" ::frontpage]
|
||||
["foo" ::foo]
|
||||
["bar" ::bar]])]
|
||||
(is (= (r/map->Match
|
||||
{:template "/"
|
||||
:data {:name ::frontpage}
|
||||
|
|
@ -51,10 +52,11 @@
|
|||
(rf/match-by-name! router ::asd)))))))))
|
||||
|
||||
(testing "schema coercion"
|
||||
(let [router (r/router ["/"
|
||||
[":id" {:name ::foo
|
||||
:parameters {:path {:id s/Int}
|
||||
:query {(s/optional-key :mode) s/Keyword}}}]]
|
||||
(let [router (rf/router
|
||||
["/"
|
||||
[":id" {:name ::foo
|
||||
:parameters {:path {:id s/Int}
|
||||
:query {(s/optional-key :mode) s/Keyword}}}]]
|
||||
{:compile rc/compile-request-coercers
|
||||
:data {:coercion rsc/coercion}})]
|
||||
|
||||
|
|
@ -108,11 +110,12 @@
|
|||
|
||||
(deftest trailing-slash-handling-test
|
||||
(testing ":both"
|
||||
(let [router (r/router ["/"
|
||||
["" ::frontpage]
|
||||
["foo" ::foo]
|
||||
["bar/" ::bar]]
|
||||
{:trailing-slash-handling :both})]
|
||||
(let [router (rf/router
|
||||
["/"
|
||||
["" ::frontpage]
|
||||
["foo" ::foo]
|
||||
["bar/" ::bar]]
|
||||
{:trailing-slash-handling :both})]
|
||||
(is (= (r/map->Match
|
||||
{:template "/foo"
|
||||
:data {:name ::foo}
|
||||
|
|
@ -136,10 +139,11 @@
|
|||
(rf/match-by-path router "/bar"))) ))
|
||||
|
||||
(testing ":add"
|
||||
(let [router (r/router ["/"
|
||||
["" ::frontpage]
|
||||
["foo" ::foo]
|
||||
["bar/" ::bar]]
|
||||
(let [router (rf/router
|
||||
["/"
|
||||
["" ::frontpage]
|
||||
["foo" ::foo]
|
||||
["bar/" ::bar]]
|
||||
{:trailing-slash-handling :add})]
|
||||
(is (= (r/map->Match
|
||||
{:template "/foo"
|
||||
|
|
@ -164,10 +168,11 @@
|
|||
(rf/match-by-path router "/bar")))))
|
||||
|
||||
(testing ":remove"
|
||||
(let [router (r/router ["/"
|
||||
["" ::frontpage]
|
||||
["foo" ::foo]
|
||||
["bar/" ::bar]]
|
||||
(let [router (rf/router
|
||||
["/"
|
||||
["" ::frontpage]
|
||||
["foo" ::foo]
|
||||
["bar/" ::bar]]
|
||||
{:trailing-slash-handling :remove})]
|
||||
(is (= (r/map->Match
|
||||
{:template "/foo"
|
||||
|
|
|
|||
Loading…
Reference in a new issue