metosin / reitit

A fast data-driven routing library for Clojure/Script
https://cljdoc.org/d/metosin/reitit/
Eclipse Public License 1.0
1.43k stars 257 forks source link

`:swagger/example` does not work when used with `{:parameters {:form ..` #425

Open pablo-develop opened 4 years ago

pablo-develop commented 4 years ago

I would expect to see the the same example for both use cases (:body and :form) but thats not the case

Screen Shot 2020-07-23 at 17 54 47

here is a reproducible example:

(ns example.server
  (:require [reitit.ring :as ring]
            [reitit.coercion.spec]
            [reitit.swagger :as swagger]
            [reitit.swagger-ui :as swagger-ui]
            [reitit.ring.coercion :as coercion]
            [reitit.dev.pretty :as pretty]
            [reitit.ring.middleware.muuntaja :as muuntaja]
            [reitit.ring.middleware.exception :as exception]
            [reitit.ring.middleware.parameters :as parameters]
            [ring.adapter.jetty :as jetty]
            [muuntaja.core :as m]
            [clojure.spec.alpha :as s]
            [spec-tools.core :as st]))

(s/def ::my-spec (st/spec
                  {:spec string?
                   :description "description"
                   :swagger/example "swagger-example"}))

(def app
  (ring/ring-handler
   (ring/router
    [["/swagger.json"
      {:get {:no-doc true
             :swagger {:info {:title "my-api"}}
             :handler (swagger/create-swagger-handler)}}]
     ["/foo-form"
      {:post {:summary "plus with spec body parameters"
              :parameters {:form (s/keys :req-un [::my-spec])}
              :handler (fn [_]
                         {:status 200
                          :body {}})}}]
     ["/foo-body"
      {:post {:summary "plus with spec body parameters"
              :parameters {:body (s/keys :req-un [::my-spec])}
              :handler (fn [_]
                         {:status 200
                          :body {}})}}]]

    {;;: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]}})
   (ring/routes
    (swagger-ui/create-swagger-ui-handler
     {:path "/"
      :config {:validatorUrl nil
               :operationsSorter "alpha"}})
    (ring/create-default-handler))))

(defn start []
  (jetty/run-jetty #'app {:port 3000, :join? false})
  (println "server running in port 3000"))

(comment
  (start))
miikka commented 4 years ago

As far as I can tell, Swagger 2.0 specification does not support examples for form data. We do generate an example field for form data parameters, but it should not be there according to the spec.

However, it seems to me that Swagger UI might support x-example field for form data. If someone can figure out if that works, a PR fixing this would be welcome. I.e. now we generate Swagger like this for formData (for the example above):

"parameters": [
  {
    "in": "formData",
    "name": "my-spec",
    "description": "description",
    "type": "string",
    "required": true,
    "title": "example.server/my-spec",
    "example": "swagger-example"
  }
]

Maybe it would work if it was like this?

"parameters": [
  {
    "in": "formData",
    "name": "my-spec",
    "description": "description",
    "type": "string",
    "required": true,
    "title": "example.server/my-spec",
    "x-example": "swagger-example"
  }
]