Fork me on GitHub
#reitit
<
2018-06-19
>
valerauko15:06:55

@ikitommi in the end i wrote the swagger specs by hand. it'd be way too verbose in clojure spec

valerauko15:06:16

i found the description syntax in the official docs after quite a bit of searching: https://swagger.io/specification/#xmlObject

valerauko16:06:09

can reitit output stuff in the format of openapi 3.0 instead of swagger (2.0)?

valerauko16:06:56

oh i just found your issue about that

ikitommi16:06:35

@vale you can return it if you write it manually, but yeah, there is a issue to support the schema/spec -> openapi3 conversion. Help welcome on that.

valerauko16:06:54

is there significant difference between 2.0 and 3.0?

ikitommi16:06:22

actually, the swagger-code always writes the Swagger2 header, so it might not work: https://github.com/metosin/reitit/blob/master/modules/reitit-swagger/src/reitit/swagger.cljc#L81

valerauko16:06:25

as in, anything breaking if i just changed the swagger "2.0" to openapi 3.0.1 ?

ikitommi16:06:36

there are some blogs about the differences, basically the request bodys are per content-type + better support for json-schema (`any-of` & one-of)

ikitommi16:06:23

the coercion parameter model is currently modelled based on ring & swagger2, e.g. there is only one type of :body per endpoint.

ikitommi16:06:50

so to support openapi3, we should think if the coercion parameter model should change too. Today I think it shouldn't.

ikitommi16:06:22

having and endpoint, which takes different body-formats (one per content-type) seems like an odd-case.

ikitommi16:06:43

Can't figure out who would need that.

valerauko16:06:47

sadly that's exactly the case i'm facing -- and it's an rcf "standard" even

ikitommi16:06:01

oh, what are you doing?

valerauko16:06:53

a protocol for looking up users etc, called webfinger. currently mostly used in distributed social media such as mastodon. this is how i modeled its lookup endpoint in openapi: https://pastebin.com/uBrv9UuU

valerauko16:06:22

its main lookup endpoint has to respond to both xml and json

ikitommi16:06:29

oh, I see. thanks for clearing that out. hmm.

ikitommi16:06:04

actually, I might work as the merge is overwriting the defaults with your settings:

(->> (dissoc swagger :id)
                       (merge {:swagger "2.0"
                               :x-id ids}))

ikitommi16:06:22

=> just add :openapi "3.0.2" and it's there.

ikitommi16:06:59

you have to update the ring-swagger-ui to the latest so it works too, add this to dependencies [metosin/ring-swagger-ui "3.9.0"]

ikitommi16:06:27

but... you don't get much help from the coercion with openapi. ideas welcome.

valerauko16:06:00

wow that's great! i didn't realize i could just throw in options like that

valerauko16:06:16

first i'd just like to document it, if it can't be coerced well so be it

ikitommi16:06:12

what if (in the future), there would be: reitit-openapi module, with own coercion middleware/interceptors, where the :body is read from under the content-type key.

valerauko16:06:08

would it be necessary to split?

valerauko17:06:21

would it be very difficult to implement a conditional branch where openapi 3.0 features would be "detected" and used if present?

ikitommi17:06:51

I could be possible. I think the swagger can be deprecated at some point.

ikitommi17:06:22

ok, actually if the only difference is the body parameters, the coercion middleware/interceptor could be shared.

ikitommi17:06:49

["/api"
 {:openapi {:id ::math, :version "3.0.1"}}

 ["/openapi.json"
  {:get {:no-doc true
         :openapi {:info {:title "my-api"}}
         :handler (openapi/create-openapi-handler)}}]

 ["/spec"
  {:coercion spec/coercion
   :openapi {:tags ["spec"]}}

  ["/plus"
   {:get {:summary "plus with spec query parameters"
          :parameters {:query {:x int?, :y int?}}
          :responses {200 {:body {:total int?}}}
          :handler (fn [{{{:keys [x y]} :query} :parameters}]
                     {:status 200
                      :body {:total (+ x y)}})}
    :post {:summary "plus with spec body parameters"
           :parameters {:body {"application/json" {:x int?, :y int?}
                               "application/xml"} {:x' int?, :y' int?}}
           :responses {200 {"application/json" {:body {:total int?}}
                            "application/xml" {:body {:total' int?}}}}
           :handler (fn [{{:keys [:muuntaja/format]}
                          {{:keys [x y x' y']} :body} :parameters}]
                      {:status 200
                       :body (case format
                               "application/json" {:total (+ x y)}
                               "application/xml" {:total' (+ x' y')})})}}]]]

ikitommi17:06:36

something like that, in the pure openapi-world.

valerauko17:06:00

i was struggling with describing the output though, not the parameters

valerauko17:06:11

so it'd be something like

:responses {200 {:body {"application/json" json-schema
                        "application/xml" xml-schema} }
            500 {:body {"text/plain" "the world has ended"}}

ikitommi17:06:27

👍 updated my example too.

👍 1
ikitommi17:06:37

well, that would be trivial to implement.

valerauko17:06:51

i'd be happy to help implementing it if you can point me in the right direction (i'm not familiar with reitit or ring-swagger's source code)

ikitommi17:06:59

I'll collect all the relevant pointers I can find to the issue, hopefully tomorrow. Heading to holidays on next wed, will be off the grid for ~3 weeks.

👍 1
💯 1
valerauko17:06:27

that sounds great! (the three weeks holiday thing sounds great too)