bidi icon indicating copy to clipboard operation
bidi copied to clipboard

Route Segments with spaces in them dont get matched...

Open twillis opened this issue 9 years ago • 7 comments

Was trying out some things because I want to move an app off of secretary. This could be a misunderstanding on my part. but this is surprising that path-for can give me a url that wont match.

(ns apollo.client.routes
  (:require [bidi.bidi :as bidi]))


(def routes ["/" {"" :home-page
                 ["artists/" :artist] {"" :artist-detail
                                       ["/albums/" :album] :album-detail}
                 true :not-found}])

(def test-route "/artists/Faith No More/albums/Angel Dust")
(= test-route (bidi/path-for routes :album-detail :artist "Faith No More" :album "Angel Dust")) # true
(bidi/match-route routes test-route)  # {:handler :not-found}

twillis avatar Jan 02 '17 17:01 twillis

If you URLEncode, it still doesn't work. :\

solussd avatar Jan 18 '17 02:01 solussd

@twillis I found a workaround. If you use [#".+" :artist] and [#".+" :album] instead of the bare keywords it'll work. :)

solussd avatar Jan 18 '17 02:01 solussd

@solussd thanks for the suggestion, I will give that a shot.

twillis avatar Jan 19 '17 14:01 twillis

@solussd thanks for the workaround, I was really struggling to understand how to deal with spaces and colons.

manuel-uberti avatar May 16 '17 15:05 manuel-uberti

Another workaround if you want to have this applied globally is to overwrite the protocol for matching pattern segments:

In my case I had to allow colons on dozens of endpoints and did it that way:

    (extend-protocol bidi.bidi/PatternSegment
      clojure.lang.Keyword
      (segment-regex-group [_] "[A-Za-z0-9\\-\\_\\.\\:]+")
      (param-key [this] this)
      (transform-param [_] identity)
      (unmatch-segment [this params]
        (if-let [v (this params)]
          (bidi.bidi/encode-parameter v)
          (throw (ex-info (str "Cannot form URI without a value given for "
                               this " parameter")
                          {})))))

Maybe that could mean this would be nicer to have segment-regex-group in a separate protocol to avoid the repetition of the other functions involved.

mpenet avatar Nov 02 '17 08:11 mpenet

Thanks for bidi! It's lovely, we use it every day, and if it didn't exist we'd have to start by inventing it.

@twillis I found a workaround. If you use [#".+" :artist] and [#".+" :album] instead of the bare keywords it'll work. :)

This workaround gets it to match, but for me, in cljs, it's breaking the :route-params:

cljs.user=> (require '[bidi.bidi :as bidi])
nil
cljs.user=> (def routes ["/" [["a/" {[:b] :a}]]])
#'cljs.user/routes
cljs.user=> (bidi/match-route routes "/a/b")
{:route-params {:b "b"}, :handler :a}

Cool.

cljs.user=> (bidi/match-route routes "/a/b%20f")
nil

That's this issue, %20 causes it to fail to match.

cljs.user=> (def routes ["/" [["a/" {[#".+" :b] :a}]]])
#'cljs.user/routes
cljs.user=> (bidi/match-route routes "/a/b%20f")
{:route-params {:b "f"}, :handler :a}

This now matches, but I expected :route-params {:b "b f"} --- perhaps I did the regex wrong?

cljs.user=> (def routes ["/" [["a/" {[#"(.+)" :b] :a}]]])
#'cljs.user/routes
cljs.user=> (bidi/match-route routes "/a/b%20f")
{:route-params {:b "b "}, :handler :a}
cljs.user=> 

I tried to get clever with the parens, but now the route param is "b " (it dropped the last character of the string, so the 'f' was lost).

Hopefully someone here can help! Regardless, thanks to all for your time and consideration.

harold avatar Feb 01 '22 22:02 harold

Wow, I just lost too much time trying to figure out why a url-encoded email in the path parms works in clojure but not clojurescript with[#".*" :email]. Thanks for the workaround @harold

jrwdunham avatar Feb 24 '24 02:02 jrwdunham