This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-02-12
Channels
- # aleph (22)
- # aws (7)
- # babashka (17)
- # beginners (69)
- # chlorine-clover (9)
- # cider (2)
- # clj-kondo (3)
- # cljdoc (30)
- # clojure (113)
- # clojure-dev (30)
- # clojure-europe (11)
- # clojure-italy (2)
- # clojure-nl (16)
- # clojure-spec (1)
- # clojure-sweden (3)
- # clojure-uk (17)
- # clojurescript (77)
- # cryogen (12)
- # data-science (5)
- # datomic (27)
- # duct (2)
- # emacs (37)
- # fulcro (24)
- # graphql (2)
- # kaocha (1)
- # lambdaisland (27)
- # leiningen (4)
- # off-topic (15)
- # onyx (1)
- # other-lisps (3)
- # re-frame (94)
- # reagent (2)
- # reitit (20)
- # ring (1)
- # shadow-cljs (66)
- # spacemacs (5)
- # sql (59)
- # tools-deps (140)
- # vim (1)
- # xtdb (17)
I usually have some validation in the spec itself if I plan to teach my consumers about some strict rules of the system
for example, in my case, I cannot have a credit contract that its future value is smaller than the acquisition value. This sort of validation usually is a mistake from the users and I deal with it in the very beginning.
makes sense. I guess I get a bit confused at where I should draw the line between contract validation and an internal validation logic (assuming contract validation can get arbitrarily complex) and that makes me think if I should be doing validation at the contract level at all
another question: is it possible to spec a response with the headers you expect it to return?
I have not tried yet, but I imagine that if you try :responses {:headers (s/keys :req-un [::my-key])}
I would not be so impressed that it works 😃
@boyanb if you use something like Integrant REPL, it should do it for you. There is an integrant sample project.
@plins no trivial way to do that, but you can always add a custom middleware/interceptor for the swagger-endpoint and walk & transform all the models in the return. asked many times, happy to hear suggestions how to do this better (or and example to the docs mw to do this)
Ill try to do so, and If I succeed Ill post it here to see if its ok then add to the docs or something but If I try to do a request from the swager interface, do you think it will send to the server the kebab-case instead of the camelCase?
if the swagger js client isnt smart enough than the only option I can think of is adding a middleware (before the validation) to convert all the keys not sure if this is efficient
hmm.. the coercion
does both transformation & validation, and there is no hook to do anything in between those two steps, but if you want to do it before coercion, add the mw before coercion/coerce-request-middleware
. For responses, a separate mw before coercion/coerce-response-middleware
.
oh, but for the request-part… the parameters are copied under :parameters
by the request-coercion-mddleware, so any step before that, you would need to read those from the original location, e.g. :body
-params from :body-parameters
I think #malli solved this nicely: you can plug in a chain of transformers and they happen at right time.
with malli, you can create a transformer chain like:
(mt/transformer
;; first run schema-based transformations named :before
{:name :before}
;; then strip out extra keys based on schema
(mt/strip-extra-keys-transformer)
;; run json-things
(mt/json-transformer)
;; run custom things
{:name :after}
;; add default values
(mt/default-value-transformer))
… and one can plug in :before
and :after
transformations for both request and response:
[:and
{:decode/before str/lower
:decode/after (partial str ".}
:encode/after str/upper} string?]
ping @plinsthere is a option to print out diffs in the request/response chain by the mw, if that helps: https://github.com/metosin/reitit/blob/master/examples/ring-malli-swagger/src/example/server.clj#L71
ok thanks very much for the input, I think Ill be able to come up with a working version soon so we can discuss whats the best way to do this? I came up with 3 middlewares (on the transform the swagger object, the other one to transform the request and the last to transform the response) should I put them in some module like middleware/swagger and create a PR ? or you prefer to dont incorporate that into reitit and a simple working example on the wiki is enough? or both?
https://gist.github.com/pablo-develop/76eb66f6ea9f4db19a86aadf59a4d188 here is an initial draft, any feedback would be awesome, not sure if it cover all cases but I created some complex endpoints and everything seems fine
with malli, you can create a transformer chain like:
(mt/transformer
;; first run schema-based transformations named :before
{:name :before}
;; then strip out extra keys based on schema
(mt/strip-extra-keys-transformer)
;; run json-things
(mt/json-transformer)
;; run custom things
{:name :after}
;; add default values
(mt/default-value-transformer))
… and one can plug in :before
and :after
transformations for both request and response:
[:and
{:decode/before str/lower
:decode/after (partial str ".}
:encode/after str/upper} string?]
ping @plins