1

I'm using compojure-api, and I'm looking for a function that, given my api route structure thingie and a request, returns the Route record (or :name) for that request, without applying its handler.

I've been able to find kind of the inverse of what I'm looking for in compojure.api.routes/path-for, which, given a :name, returns the path for the corresponding route. In the same namespace there are also functions like get-routes which seem promising, but I've yet to find exactly what I'm looking for.

In other words, given this simple example

(defapi my-api
  (context "/" []
    (GET "/myroute" request
      :name :my-get
      (ok))
    (POST "/myroute" request
      :name :my-post
      (ok))))

I'm looking for a function foo that works like this

(foo my-api (mock/request :get "/myroute"))
;; => #Route{:path "/myroute", :method :get, :info {:name :my-get, :public {:x-name :my-get}}}
;; or
;; => :my-get

Any ideas?

Marxama
  • 425
  • 3
  • 13

1 Answers1

3

my-api is defined as a Route Record, so you can evaluate it at the repl to see what it looks like:

#Route{:info {:coercion :schema},
       :childs [#Route{:childs [#Route{:path "/",
                                       :info {:static-context? true},
                                       :childs [#Route{:path "/myroute",
                                                       :method :get,
                                                       :info {:name :my-get, :public {:x-name :my-get}}}
                                                #Route{:path "/myroute",
                                                       :method :post,
                                                       :info {:name :my-post, :public {:x-name :my-post}}}]}]}]}

There are helpers in compojure.api.routes to transform the structure:

(require '[compojure.api.routes :as routes])

(routes/get-routes my-api)
; [["/myroute" :get {:coercion :schema, :static-context? true, :name :my-get, :public {:x-name :my-get}}]
;  ["/myroute" :post {:coercion :schema, :static-context? true, :name :my-post, :public {:x-name :my-post}}]]

, which effectively flattens the route tree while retaining the order. For reverse routing there is:

(-> my-api
    routes/get-routes
    routes/route-lookup-table)
; {:my-get {"/myroute" {:method :get}}
;  :my-post {"/myroute" {:method :post}}}

More utilities can be added if needed.

Hope this helps.

Tommi Reiman
  • 268
  • 1
  • 6
  • Thanks Tommi! That gets it almost all the way, it's just the final path matching that I'm reluctant to do myself (it easily gets complicated when path params and so on are included). But I think it should work to use Clout for that, since that's what Compojure uses under the hood. – Marxama Nov 15 '17 at 07:32
  • I think that would be useful tool, would you like to do a PR out If that when done? – Tommi Reiman Nov 16 '17 at 08:22
  • Absolutely, will do! – Marxama Nov 16 '17 at 12:57