OpenAPI middleware¶
This glues everything together between flask-marshmallow-openapi and your Flask
application.
In it’s simplest form it defines API title, app’s package name (for
marshmallow.Schemas lookup) and few other high level docs parameters.
from flask_marshmallow_openapi import OpenAPISettings, OpenAPI
conf = OpenAPISettings(
api_version="v1",
api_name="Foobar API",
app_package_name="foobar_api",
mounted_at="/v1"
)
docs = OpenAPI(config=conf)
docs.init_app(app)
Once init_app is called, middleware will register routes for swagger.json,
swagger.yaml, ReDoc and SwaggerUI:
$ flask routes
Endpoint Methods Rule
--------------------- ------- -------------------------------
# ...
open_api.re_doc GET /v1/docs/re_doc
open_api.static GET /v1/docs/static/<path:filename>
open_api.swagger_json GET /v1/docs/static/swagger.json
open_api.swagger_ui GET /v1/docs/swagger_ui
open_api.swagger_yaml GET /v1/docs/static/swagger.yaml
static GET /static/<path:filename>
# ...
Besides that, there are few more optional features that it provides which are described below.
Custom OpenAPI template¶
It is possible to inject custom Jinja2 template for swagger.json. The most useful
case for this is documenting tags used to group app’s routes and injecting servers
component:
For example, we can use my_openapi_template.yaml:
# my_openapi_template.yaml
title: "{{ api_name }}"
openapi_version: 3.0.2
servers:
- url: http://127.0.0.1:5000
description: |
Flask dev server running locally on developer machine
- url: https://foo.example.com
description: Live API server
tags:
- name: Books
description: |
Docs for Books tag
Look I can Markdown!
| foo | bar | baz |
| --- | --- | --- |
| 1 | 2 | 3 |
| 4 | 5 | 6 |
We then distribute this template like any other Flask template but provide loader to callback to OpenAPI middleware:
import importlib.resources
def load_swagger_json_template(api_name: str, api_version: str):
text = flask.render_template_string(
importlib.resources.files(app_resources_package)
.joinpath("my_openapi_template.yaml")
.read_text(),
api_name=api_name,
)
data = yaml.full_load(text)
data["version"] = api_version
return data
conf = OpenAPISettings(
api_version="v1",
api_name="Foobar API",
app_package_name="foobar_api",
mounted_at="/v1",
swagger_json_template_loader=load_swagger_json_template,
swagger_json_template_loader_kwargs={"api_name": "Foobar API", "api_version": "v1"},
)
docs = OpenAPI(config=conf)
docs.init_app(app)

Changelog loader¶
Similarly to custom swagger.json template, it is possible to provide callback for loading
CHANGELOG.md (or similar) file:
import importlib.resources
def load_changelog_md():
return (
importlib.resources.files(app_resources_package)
.joinpath("CHANGELOG.md")
.read_text()
)
conf = OpenAPISettings(
api_version="v1",
api_name="Foobar API",
app_package_name="foobar_api",
mounted_at="/v1",
changelog_md_loader=load_changelog_md
)
docs = OpenAPI(config=conf)
docs.init_app(app)
Doing so, will cause few more routes to be attached to Flask app:
$ flask routes
Endpoint Methods Rule
----------------------------- ------- -------------------------------
# ...
open_api.changelog GET /v1/docs/changelog
open_api.changelog_md GET /v1/docs/static/changelog.md
open_api...
# ...
/v1/docs/changelog renders given contents of CHANGELOG.md.
This can be linked from swagger.json and thus allow documentation consumers to have
easy access to API changelog:
# my_openapi_template.yaml
title: "{{ api_name }}"
openapi_version: 3.0.2
info:
description: |
Flask API for demonstrating capabilities of `flask-marshmallow-openapi`
[See CHANGELOG here](/v1/docs/changelog)
# ...
conf = OpenAPISettings(
api_version="v1",
api_name="Foobar API",
app_package_name="foobar_api",
mounted_at="/v1",
swagger_json_template_loader=load_swagger_json_template,
swagger_json_template_loader_kwargs={"api_name": "Foobar API", "api_version": "v1"},
changelog_md_loader=load_changelog_md
)
docs = OpenAPI(config=conf)
docs.init_app(app)
And result:
