servant-openapi-hs

Generate an OpenAPI 3.1 specification for
your Servant API, and partially
test that the API conforms to its specification.
Fork notice. servant-openapi-hs is a fork of
biocad/servant-openapi3, which
targets OpenAPI 3.0. This fork retargets it at OpenAPI 3.1 by building on
openapi-hs (a fork of
biocad/openapi3) instead of openapi3.
The Haskell module namespace is unchanged (Servant.OpenApi.*), and because
openapi-hs keeps the Data.OpenApi.* namespace, migrating is usually just a
dependency-name swap: servant-openapi3 → servant-openapi-hs and openapi3 →
openapi-hs. The fork keeps the upstream BSD-3-Clause license and
copyright.
Motivation
OpenAPI is a language-agnostic format for describing and documenting HTTP APIs.
This package derives an OpenAPI 3.1 specification directly from a Servant API
type, so the description stays in sync with the server, and provides combinators
to test that handlers conform to the generated schema.
A generated specification can then be used to
- display interactive documentation in any OpenAPI 3.1 viewer;
- generate clients and servers in many languages with OpenAPI Generator;
- and many other things across the OpenAPI tooling ecosystem.
Installation
servant-openapi-hs is available on
Hackage. The 5.0
series builds against openapi-hs 5; see the changelog for the
OpenAPI 3.1 port, MultiVerb support, and the openapi-hs 5 upgrade.
Add servant-openapi-hs to your package's build-depends:
build-depends: servant-openapi-hs >= 5.0 && < 6
Its OpenAPI 3.1 data model comes from
openapi-hs, which is pulled
in automatically as a transitive dependency.
Import the umbrella module:
import Servant.OpenApi
Requires GHC 9.12.4 or 9.14.1.
Building from source. To test unreleased changes, depend on this
repository directly by adding a source-repository-package stanza for
servant-openapi-hs to your cabal.project:
source-repository-package
type: git
location: https://github.com/shinzui/servant-openapi-hs.git
tag: <commit-sha>
Its openapi-hs dependency resolves from Hackage automatically.
Usage
Derive an OpenAPI 3.1 document from a Servant API type with toOpenApi:
import Data.Aeson (encode)
import Data.OpenApi (OpenApi)
import Data.Proxy (Proxy (..))
import Servant.OpenApi (toOpenApi)
spec :: OpenApi
spec = toOpenApi (Proxy :: Proxy MyApi)
-- encode spec ==> {"openapi":"3.1.0", ...}
A runnable example lives in app/GenOpenApi.hs, built as
the gen-openapi executable, which prints a complete Todo-CRUD document:
cabal run gen-openapi > openapi.json
The full API surface is unchanged from upstream; see the
Haddock documentation.
Generated specifications can be explored interactively in any OpenAPI 3.1
viewer or editor.
Validation
Generated documents are checked at three levels:
-
Round-trip — the test suite decodes each generated document back through
openapi-hs's FromJSON OpenApi, which rejects any openapi version outside
3.1.0 … 3.1.1, then compares the result for semantic equality.
-
Example-conformance — Servant.OpenApi.Test.validateEveryToJSON checks
that random values of each response type validate against the generated
schema.
-
Authoritative conformance — the gen-openapi output lints cleanly under
vacuum (0 errors). On servant ≥ 0.20.3 the
API includes a MultiVerb endpoint, so this check also validates MultiVerb
rendering against the OpenAPI 3.1 spec:
cabal run gen-openapi > openapi.json
nix run nixpkgs#vacuum-go -- lint -d openapi.json
Versioning
This package follows the Haskell
Package Versioning Policy (PVP). Versions have the
form A.B.C, optionally followed by further components, where A.B together
is the major version: it changes only when the public API breaks. A release
that only adds to the API bumps C, and one that does not touch the API bumps a
fourth component D. The PVP-recommended bound is therefore:
build-depends: servant-openapi-hs >=5.0 && <5.1
Releases up to and including 5.0.0 numbered themselves like SemVer; 4.1.0 in
particular was additive-only and would be 4.0.1 under the policy above. From
5.0.0 onward the policy holds.
License
servant-openapi-hs retains the original BSD-3-Clause license of the upstream
servant-openapi3 project,
including its copyright. See the LICENSE file for the full text;
this fork's changes are released under the same terms.
Originally derived from work by the Servant contributors (David Johnson,
Nickolay Kudasov, Maxim Koltsov, and others).