This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-01-30
Channels
- # announcements (14)
- # aws (2)
- # beginners (167)
- # calva (25)
- # cider (124)
- # cljs-dev (2)
- # cljsrn (7)
- # clojars (2)
- # clojure (113)
- # clojure-europe (2)
- # clojure-italy (6)
- # clojure-spec (30)
- # clojure-uk (90)
- # clojurescript (20)
- # code-reviews (16)
- # cursive (28)
- # data-science (2)
- # datomic (89)
- # duct (97)
- # emacs (4)
- # figwheel-main (12)
- # fulcro (37)
- # graphql (3)
- # java (3)
- # jobs (2)
- # juxt (3)
- # kaocha (37)
- # leiningen (2)
- # luminus (2)
- # off-topic (30)
- # onyx (2)
- # pathom (3)
- # qlkit (1)
- # re-frame (7)
- # reagent (2)
- # reitit (62)
- # remote-jobs (9)
- # shadow-cljs (26)
- # tools-deps (19)
- # vim (1)
- # yada (8)
home stretch - I now combine routers for performance, but now it's mixing all the swagger routes together
so I have ["/v1/" blah] and ["/v2/" blah] and I want to generate different swagger.json's
so, you can add a :id
to swagger-apis, one endpoint can belong to multiple apis too. Cool to get a real-life use case for this, just added it because it was easy to do it.
[["/v1"
{:swagger {:id ::v1}}
v1-routes common-routes
["/swagger.json" ...]
["/swagger-ui/*" ...]]
["/v2"
{:swagger {:id ::v2}}
v2-routes common-routes
["/swagger.json" ...]
["/swagger-ui/*" ...]]]
@kanwei use meta-merge meta-data like`:replace` or :displace
on the middleware vector to ignore whatever the parents have set. Here are some pointers for it: https://metosin.github.io/reitit/basics/route_data.html#nested-route-data
also, the middleware can decide not to mount on certain endpoints, using their :compile
lifecycle functions.
for example, one can safely add coercion etc. middleware to the root, it will only attach itself to routes that have :coercion
and :parameters
or :responses
defined.
we lean on`:compile` on projects a lot, one can add data like :roles #{:admin}
to route data and have a middleware mount just to those endpoints.
(def v2-routes
(reitit/router
[["/api/v2"
{:swagger {:id ::v2}
:middleware [wrap-api-account
wrap-api-validate]}
private-search-routes]
["/api/v2"
{:swagger {:id ::v2}}
public-search-routes]
["/api/v2/swagger.json"
{:get {:no-doc true
:swagger {:id ::v2
:info {:version "2.0"
:title "X"
:description "X"
:contact {:name "X"
:email "x"}}}
:handler (swagger/create-swagger-handler)
}}]]
{:data {:coercion reitit.coercion.spec/coercion
:middleware [coercion/coerce-response-middleware
coercion/coerce-request-middleware
]}}))
the vector syntax still trips me up because I'm not sure how the options maps are applied
[["/api/v2" {:middleware [wrap-x]}]
["/api/v2/swagger.json" {:middleware [wrap-x]}]
["/api/v2/ping" {:middleware [wrap-x]}]]
here the two routes are under the top-level route fragment and the route data gets merged from there (root->leafs)
[["/api/v2"
{:middleware [wrap-x]}
["/swagger.json"]
{:middleware [wrap-y]}
["/ping"]]]
(ns user
(:require [reitit.core :as r]))
(-> (r/router
["/api"
{:middleware [:api]}
["/v2"
{:middleware [:v2]}
["/ping"]
["/pong"]]])
(r/routes))
;[["/api/v2/ping" {:middleware [:api :v2]}]
; ["/api/v2/pong" {:middleware [:api :v2]}]]
internally, the routes are flattented and the data gets merged using the meta-merge rules
(-> (r/router
["/api"
{:middleware [:api]}
["/v2"
{:middleware [:v2]}
["/ping"]
["/pong"
{:middleware ^:replace [:pong]}]]])
(r/routes))
;[["/api/v2/ping" {:middleware [:api :v2]}]
; ["/api/v2/pong" {:middleware [:pong]}]]
we are about to do a swagger-like tool, but for reitit, with visualization of the merged route structure to help development
(defn merge-routers [& routers]
(reitit-core/router
(apply merge (map reitit-core/routes routers))
(assoc (apply merge (map reitit-core/options routers))
:conflicts nil)))
(reitit/ring-handler
(merge-routers controller/main-website-routes ; <---- has conflicts
register-routes <---- no conflicts
...))
I would have assumed that you could just do a normal merge of a quarantine router (controller/main-website-routes) and a regular router without having to do another {:conflicts nil}
btw, the route fragment can be empty, too. this allows route-data to be attached without adding anything to the path. like :<>
in reagent. This is a big win over compojure & others.
(-> (r/router
["" {:no-doc true}
["/ping"]
["/pong"]])
(r/routes))
;[["/ping" {:no-doc true}]
; ["/pong" {:no-doc true}]]
[["/api/v2"
{:swagger {:id ::v2}}
[private-search-routes {:middleware [wrap-api-account
wrap-api-validate]}]
[public-search-routes]]]
any way to make it work like this, or do I have to put it in another ["/api/v2"] sibling?
the private-search-routes
is most likely a vector, the data can only be after a path string. the empty fragment helps here:
[["/api/v2"
{:swagger {:id ::v2}}
["" {:middleware [wrap-api-account wrap-api-validate]}
private-search-routes]
public-search-routes]]