How to generate OpenAPI docs and validate requests
View SourceProblem
You want a machine-readable OpenAPI spec for your routes, a browsable docs page, and automatic rejection of malformed request bodies.
Generate the spec
livery_openapi:build/1 turns route metadata into an OpenAPI 3.1
document. Livery path templates (:param, *wildcard) become
{param} and gain synthesised path parameters:
Doc = livery_openapi:build(#{
info => #{title => <<"My API">>, version => <<"1.0.0">>},
routes => [
{<<"GET">>, <<"/users/:id">>, {users, show},
#{summary => <<"Fetch a user">>,
responses => #{200 => #{description => <<"the user">>}}}}
]
}).Serve it as JSON with livery_openapi:handler/1, mounted at
/openapi.json:
{<<"GET">>, <<"/openapi.json">>, livery_openapi:handler(Doc)}Serve a docs UI
Both UIs are self-contained HTML pages that load the spec from a URL; the JS bundles come from a CDN, so no static files are needed. Pick one:
%% Redoc
{<<"GET">>, <<"/docs">>, livery_openapi:redoc_handler()}
%% Swagger UI
{<<"GET">>, <<"/docs">>, livery_openapi:swagger_ui_handler()}Pass a custom spec URL to either: redoc_handler(<<"/v2/openapi.json">>).
Validate request bodies
livery_openapi_validate rejects bodies that do not match a
schema with 422, and stores the decoded body under
meta(body, _) on success:
Schema = #{
type => <<"object">>,
required => [<<"email">>],
properties => #{
<<"email">> => #{type => <<"string">>, pattern => <<"@">>},
<<"age">> => #{type => <<"integer">>, minimum => 0}
},
additionalProperties => false
}.
Stack = [{livery_openapi_validate, #{body_schema => Schema}}],Supported keywords cover type (single or a list), enum,
const, the numeric bounds (minimum/maximum/exclusive*/
multipleOf), string minLength/maxLength/pattern, object
required/properties/additionalProperties/min/maxProperties,
array items/min/maxItems/uniqueItems, and the allOf/
anyOf/oneOf combinators. A 422 body lists each failure as
{path, error}.
See also
- Reference:
livery_openapi,livery_openapi_validate - Concept: Routing