Connexion is a python framework based on Flask.
It streamlines the creation of contract-first REST APIs.
Once you have your OAS3 spec, connexion uses it to:
In [ ]:
# At first ensure connexion is installed
# together with the swagger module used to render the OAS3 spec
# in the web-ui
!pip install connexion[swagger-ui] connexion
Now run the spec in a terminal using
connexion run /code/notebooks/oas3/ex-01-info-ok.yaml
Remember:
:5000/ui path.
In [ ]:
# A request on a generic PATH on the server returns a
# nicely formatted and explicative error.
# Remember that we haven't already defined an operation.
!curl http://0.0.0.0:5000 -kv
In [ ]:
render_markdown(f'''
Open the [documentation URL]({api_server_url('ui')}) and check the outcome!
Play a bit with Swagger UI.''')
Now that we have added our metadata, we can provide informations about the endpoints. OAS3 allows multiple endpoints because good APIs have many.
Every endpoint can start with a prefix path (eg. /datetime/v1).
# One or more server
# You can add production, staging and test environments.
# We
# sandbox instances
servers:
- description: |
An interoperable API has many endpoints.
One for development...
url: https://localhost:8443/datetime/v1
- description:
One for testing in a sandboxed environment. This
is especially important to avoid clients to
test in production.
We are using the custom `x-sandbox` to identify
url: https://api.example.com/datetime/v1
x-sandbox: true
- description: |
Then we have our production endpoint.
The custom `x-healthCheck` parameter
can be used to declare how to check the API.
url: https://api.example.com/datetime/v1/status
x-healthCheck:
url: https://api.example.com/datetime/v1/status
interval: 300
timeout: 15
pathsNow we can define our first path that is the /status one.
An interoperable API should declare an URL for checking its status.
This allows implementers to plan a suitable method for testing it (eg. it could be a simple OK/KO method or can execute basic checks like. databases are reachable, smoke testing other components, ..)
operationId: get_status
responses:
'200':
description: |
The application is working properly.
content:
application/problem+json:
example:
status: 200
title: OK
detail: API is working properly.
default:
description: |
If none of the above statuses is returned, then this applies
content:
application/problem+json:
example:
status: 500
title: Internal Server Error
detail: API is not responding correctly
get /status pathWe haven't already implemented the function get_status() referenced by operationId,
so to run the spec in a terminal we tell the server
to ignore this with --stub
connexion run /code/notebooks/oas3/ex-03-02-path.yaml --stub
In [ ]:
# Exercise: what's the expected output of the following command?
!curl http://0.0.0.0:5000/datetime/v1/status
# Exercise: what happens if you GET an unexisting path?
!curl http://0.0.0.0:5000/datetime/v1/MISSING
Solution on the unimplemented method
$ curl http://0.0.0.0:8889/datetime/v1/status
{
"detail": "Empty module name",
"status": 501,
"title": "Not Implemented",
"type": "about:blank"
}
Solution on other paths
$ curl http://0.0.0.0:8889/datetime/v1/missing
{
"detail": "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.",
"status": 404,
"title": "Not Found",
"type": "about:blank"
}
OAS3 allows defining, using and reusing schemas.
They can be defined inline, in the component section or referenced from another file, like below.
The URL fragment part can be used to navigate inside the yaml (eg. #/schemas/Problem).
components:
schemas:
Problem:
$ref: 'https://teamdigitale.github.io/openapi/0.0.5/definitions.yaml#/schemas/Problem'
In [ ]:
print(show_component('https://teamdigitale.github.io/openapi/0.0.5/definitions.yaml#/schemas/Problem'))
In [ ]:
# Exercise: use the yaml and requests libraries
# to download the Problem schema
from requests import get
ret = get('https://teamdigitale.github.io/openapi/0.0.5/definitions.yaml')
# Yaml parse the definitions
definitions = yaml.safe_load(ret.content)
# Nicely print the Problem schema
print(yaml.dump(definitions['schemas']['Problem']))
In [ ]:
### Exercise
# Read the definitions above
# - https://teamdigitale.github.io/openapi/0.0.5/definitions.yaml
#
# Then use this cell to list all the structures present in definitions
In [ ]:
for sections, v in definitions.items():
for items, vv in v.items():
print(f'{sections}.{items}')
Edit ex-03-02-path.yaml so that every /status response uses
the Problem schema.
Look at simple.yaml to see a complete implementation.
In [ ]:
## Exercise
#Test the new setup