Liking cljdoc? Tell your friends :D

OpenAPI Support

Stability: alpha

Reitit can generate OpenAPI 3.1.0 documentation. The feature works similarly to Swagger documentation.

The main example is examples/openapi. The ring-malli-swagger and ring-spec-swagger examples also have OpenAPI documentation.

OpenAPI data

The following route data keys contribute to the generated swagger specification:

keydescription
:openapimap of any openapi data. Can contain keys like :deprecated.
:no-docoptional boolean to exclude endpoint from api docs
:tagsoptional set of string or keyword tags for an endpoint api docs
:summaryoptional short string summary of an endpoint
:descriptionoptional long description of an endpoint. Supports http://spec.commonmark.org/
:openapi/request-content-typesSee the Per-content-type-coercions section below.
:openapi/response-content-typesSee the Per-content-type-coercions section below. vector of supported response content types. Defaults to ["application/json"]. Only needed if you use the [:response nnn :content :default] coercion.

Coercion keys also contribute to the docs:

keydescription
:parametersoptional input parameters for a route, in a format defined by the coercion
:requestoptional description of body parameters, possibly per content-type
:responsesoptional descriptions of responses, in a format defined by coercion

Per-content-type coercions

Use :request coercion (instead of :body) to unlock per-content-type coercions. This also lets you specify multiple named examples. See Coercion for more info. See also the openapi example.

["/pizza"
 {:get {:summary "Fetch a pizza | Multiple content-types, multiple examples"
        :responses {200 {:description "Fetch a pizza as json or EDN"
                         :content {"application/json" {:schema [:map
                                                                [:color :keyword]
                                                                [:pineapple :boolean]]
                                                       :examples {:white {:description "White pizza with pineapple"
                                                                          :value {:color :white
                                                                                  :pineapple true}}
                                                                  :red {:description "Red pizza"
                                                                        :value {:color :red
                                                                                :pineapple false}}}}
                                   "application/edn" {:schema [:map
                                                               [:color :keyword]
                                                               [:pineapple :boolean]]
                                                      :examples {:red {:description "Red pizza with pineapple"
                                                                       :value (pr-str {:color :red :pineapple true})}}}}}}

The special :default content types map to the content types supported by the Muuntaja instance. You can override these by using the :openapi/request-content-types and :openapi/response-content-types keys, which must contain vector of supported content types. If there is no Muuntaja instance, and these keys are not defined, the content types will default to ["application/json"].

OpenAPI spec

Serving the OpenAPI specification is handled by reitit.openapi/create-openapi-handler. It takes no arguments and returns a ring handler which collects at request-time data from all routes and returns an OpenAPI specification as Clojure data, to be encoded by a response formatter.

You can use the :openapi route data key of the create-openapi-handler route to populate the top level of the OpenAPI spec.

Example:

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

If you need to post-process the generated spec, just wrap the handler with a custom Middleware or an Interceptor.

Swagger-ui

Swagger-UI is a user interface to visualize and interact with the Swagger specification. To make things easy, there is a pre-integrated version of the swagger-ui as a separate module. See reitit.swagger-ui/create-swagger-ui-handle

Finetuning the OpenAPI output

There are a number of ways you can specify extra data that gets included in the OpenAPI spec.

Custom OpenAPI data

The :openapi route data key can be used to add top-level or route-level information to the generated OpenAPI spec.

A straightforward use case is adding "externalDocs":

["/account"
 {:get {:summary "Fetch an account | Recursive schemas using malli registry, link to external docs"
        :openapi {:externalDocs {:description "The reitit repository"
                                 :url "https://github.com/metosin/reitit"}}
        ...}}]

In a more complex use case is providing "securitySchemes". See the openapi example for a working example of "securitySchemes". See also the OpenAPI docs

Annotating schemas

You can use malli properties, schema-tools data or spec-tools data to annotate your models with examples, descriptions and defaults that show up in the OpenAPI spec.

This approach lets you add additional keys to the OpenAPI Schema Objects. The most common ones are default and example values for parameters.

Malli:

["/plus"
 {:post
  {:parameters
   {:body [:map
           [:x
            {:title "X parameter"
             :description "Description for X parameter"
             :json-schema/default 42}
            int?]
           [:y int?]]}}}]

Schema:

["/plus"
 {:post
  {:parameters
   {:body {:x (schema-tools.core/schema s/Num {:description "Description for X parameter"
                                               :openapi/example 13
                                               :openapi/default 42})
           :y int?}}}}]

Spec:

["/plus"
 {:post
  {:parameters
   {:body (spec-tools.data-spec/spec ::foo
                                     {:x (schema-tools.core/spec {:spec int?
                                                                  :description "Description for X parameter"
                                                                  :openapi/example 13
                                                                  :openapi/default 42})
                                      :y int?}}}}}]

Adding examples

Adding request/response examples have been mentioned above a couple of times above. Here's a summary of the different ways to do it:

  1. Add an example to the schema object using a :openapi/example (schema, spec) or :json-schema/example (malli) key in your schema/spec/malli model metadata. See the examples above.
  2. Use :example (a single example) or :examples (named examples) with per-content-type coercion.

Caveat! When adding examples for query parameters (or headers), you must add the examples to the individual parameters, not the map schema surrounding them. This is due to limitations in how OpenAPI represents query parameters.

;; Wrong!
{:parameters {:query [:map
                      {:json-schema/example {:a 1}}
                      [:a :int]]}}
;; Right!
{:parameters {:query [:map
                      [:a {:json-schema/example 1} :int]]}}

Named schemas

OpenAPI supports reusable schema objects that can be referred to with the "$ref": "#/components/schemas/Foo" json-schema syntax. This is useful when you have multiple endpoints that use the same schema. It can also make OpenAPI-based code nicer for consumers of your API. These schemas are also rendered in their own section in Swagger UI.

Reusable schema objects are generated for Malli :refs and vars. The openapi example showcases this.

Currently (as of 0.7.2), reusable schema objects are not generated for Plumatic Schema or Spec.

Can you improve this documentation? These fine people already did:
Joel Kaasinen & Martín Varela
Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close