This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-02-18
Channels
- # announcements (1)
- # asami (17)
- # babashka (43)
- # beginners (36)
- # biff (2)
- # calva (24)
- # clerk (3)
- # clj-kondo (9)
- # cljdoc (18)
- # clojure (16)
- # clojure-berlin (1)
- # clojure-europe (7)
- # clojurescript (8)
- # clr (4)
- # conjure (3)
- # cursive (2)
- # emacs (15)
- # funcool (4)
- # humbleui (2)
- # hyperfiddle (116)
- # kaocha (3)
- # malli (5)
- # membrane (23)
- # off-topic (16)
- # pathom (3)
- # reitit (25)
- # releases (3)
- # shadow-cljs (13)
- # xtdb (6)
I would like to imitate the url format of an existing service using reitit , the format is https://internal-service/ABCDEFHIJK do reitit path params permit this format? Some initial testing with the following doesn't seem to work
["/:doc-id" {:post {:handler (fn [{:keys [path-params]}]
{:status 200
;; :headers {"Content-Type" "image/png"}
:body path-params})}}]
post a full router instead of a stub — i want to rule out the possibility of you including a root route and accidentally introducing an extra slash
(def app
(ring/ring-handler
(ring/router
[["/" {:tags "root"}
["/:doc-id" {:post {:handler (fn [{:keys [path-params]}]
{:status 200
;; :headers {"Content-Type" "image/png"}
:body path-params})}}]]
["/swagger.json"
{:get {:no-doc true
:swagger {:info {:title "my-api"
:description "with reitit-ring"}}
:handler (swagger/create-swagger-handler)}}]
]
{;;:reitit.middleware/transform dev/print-request-diffs ;; pretty diffs
;;:validate spec/validate ;; enable spec validation for route data
;;:reitit.spec/wrap spell/closed ;; strict top-level validation
:exception pretty/exception
:data {:coercion reitit.coercion.spec/coercion
:muuntaja m/instance
:middleware [;; swagger feature
swagger/swagger-feature
;; query-params & form-params
parameters/parameters-middleware
;; content-negotiation
muuntaja/format-negotiate-middleware
;; encoding response body
muuntaja/format-response-middleware
;; exception handling
exception/exception-middleware
;; decoding request body
muuntaja/format-request-middleware
;; coercing response bodys
coercion/coerce-response-middleware
;; coercing request parameters
coercion/coerce-request-middleware
;; multipart
multipart/multipart-middleware]}})
(ring/routes
(ring/create-resource-handler {:path "/public"})
(swagger-ui/create-swagger-ui-handler
{:path "/"
:config {:validatorUrl nil
:operationsSorter "alpha"}})
(ring/create-default-handler))))
I don’t know how to explain it well in English, so here’s some code denoting how the route tree works
[["/"
[""] ; /
[":doc-id"]] ; /:doc-id
["/swagger.json"]] ; /swagger.jsobn
What is the address you visited in your browser? What happens if you run (r/match-by-path your-router "/123")
/:doc-id
and /swagger.json
are conflicting paths. Set either one to :conflicting true
Here’s an example from my clojurescript REPL
cljs.user> (-> (r/router
[["/"
["" {:name ::root}]
[":id" {:name ::root.id
:conflicting true}]]
["/swagger.json" {:name ::swagger
:conflicting true}]])
(r/match-by-path "/123"))
#reitit.core.Match{:template "/:id", :data {:name :cljs.user/root.id, :conflicting true}, :result nil, :path-params {:id "123"}, :path "/123"}
The reason this happens is because path params are strings (until you coerce them), so reitit has no way to tell whether you wanted /:id
or /swagger.json
when gets a path like / + string
. By setting the paths as conflicting, reitit will know ahead of time that it will have to resolve the conflict
getting further now , now my swagger is http 405:
[["/"
["" {:name ::root}]
[":doc-id" {:name ::root.doc-id
:conflicting true
}]]
["/swagger.json"
{:name ::swagger
:conflicting true
:get {:no-doc true
:swagger {:info {:title "my-api"
:description "with reitit-ring"}}
:handler (swagger/create-swagger-handler)}}]
]
sre.zomgd.core> (reitit.core/match-by-path app "/123")
Execution error (IllegalArgumentException) at reitit.core/eval54459$fn$G (core.cljc:38).
No implementation of method: :match-by-path of protocol: #'reitit.core/Router found for class: clojure.lang.AFunction$1
i think my router is typo'd perhaps going to start from scratch and see + upgrade to latest version
Conflict resolution algorithm isn’t documented well in Reitit, unfortunately. But in short, the first match wins in a conflict.
That is to say, if we have
[["/:id"]
["/swagger.json"]]
then /:id
always wins in a conflict. However, if we have the route tree
[["/swagger.json"]
["/:id"]]
then the path /swagger.json
will be matched against /swagger.json
first, so we get the /swagger.json
route instead of /:id
For reference, I am using [metosin/reitit "0.5.18"]
, also the latest version of the library.
@U5Y86G3KL Here is a demonstration of the first match winning in a conflict
cljs.user> (def router
(r/router
[["/swagger.json" {:conflicting true}]
["/:id" {:conflicting true}]]))
#'cljs.user/router
cljs.user> (:template (r/match-by-path router "/123"))
"/:id"
cljs.user> (:template (r/match-by-path router "/swagger.json"))
"/swagger.json"
hey @U0479UCF48H moving swagger above :doc-id + :conflicting true
did the trick! tysm for your help 🙏