Connexion - API first applications with OpenAPI/Swagger and Flask
Project description
Connexion
Connexion is a framework on top of Flask that automagically handles HTTP requests based on OpenAPI 2.0 Specification (formerly known as Swagger Spec) of your API described in YAML format. Connexion allows you to write a Swagger specification and then maps the endpoints to your Python functions. This is what makes it unique from other tools that generate the specification based on your Python code. You are free to describe your REST API with as much detail as you want and then Connexion guarantees that it will work as you specified. We built Connexion this way in order to:
Simplify the development process
Reduce misinterpretation about what an API is going to look like
Connexion Features:
Validates requests and endpoint parameters automatically, based on your specification
Provides a Web Swagger Console UI so that the users of your API can have it as a live documentation and even call your API’s endpoints through it
Handles OAuth 2 token-based authentication
Supports API versioning
Supports automatic serialization of payloads. If your specification defines that an endpoint returns JSON, Connexion will automatically serialize the return value for you and set the right content type in the HTTP header.
Why Connexion
With Connexion, you write the spec first. It then calls your Python code handling the mapping from the specification to the code. This incentivizes you to write the specification so that all of your developers can understand what your API does - even before you write a single line of code. If multiple teams depend on your APIs, you can already send them the documentation of your API. This guarantees that your API will follow the specification that you wrote. it’s not like frameworks such as Hug, which generates the specification based on what code you write. Some disadvantages of generating the specification based on code is that usually your specification is laking details and your documentation is mixed with the code logic of your application.
Other Sources/Mentions
How to Use
Prerequisites
Python 2.7 or Python 3.4+
Installing It
In your command line, type this:
$ pip install Connexion
$ python hello.py
Running It
Place your API YAML inside a folder in the root path of your application (e.g swagger/). Then run:
import connexion
app = connexion.App(__name__, specification_dir='swagger/')
app.add_api('my_api.yaml')
app.run(port=8080)
See the Connexion Pet Store Example Application for a sample specification.
Now you’re able run and use Connexion!
Dynamic Rendering of Your Specification
Connexion uses Jinja2 to allow specification parameterization through arguments parameter. You can either define specification arguments globally for the application in the connexion.App constructor, or for each specific API in the connexion.App#add_api method:
app = connexion.App(__name__, specification_dir='swagger/',
arguments={'global': 'global_value'})
app.add_api('my_api.yaml', arguments={'api_local': 'local_value'})
app.run(port=8080)
When a value is provided both globally and on the API, the API value will take precedence.
Endpoint Routing to Your Python Views
Connexion uses the operationId from each Operation Object to identify which Python function should handle each URL.
Explicit Routing:
paths:
/hello_world:
post:
operationId: myapp.api.hello_world
If you provided this path in your specification POST requests to http://MYHOST/hello_world, it would be handled by the function hello_world in myapp.api module. Optionally, you can include x-swagger-router-controller in your operation definition, making operationId relative:
paths:
/hello_world:
post:
x-swagger-router-controller: myapp.api
operationId: hello_world
Automatic Routing
To customize this behavior, Connexion can use alternative Resolvers—for example, RestyResolver. The RestyResolver will compose an operationId based on the path and HTTP method of the endpoints in your specification:
from connexion.resolver import RestyResolver
app = connexion.App(__name__)
app.add_api('swagger.yaml', resolver=RestyResolver('api'))
paths:
/:
get:
# Implied operationId: api.get
/foo:
get:
# Implied operationId: api.foo.search
post:
# Implied operationId: api.foo.post
'/foo/{id}':
get:
# Implied operationId: api.foo.get
put:
# Implied operationId: api.foo.post
copy:
# Implied operationId: api.foo.copy
delete:
# Implied operationId: api.foo.delete
RestyResolver will give precedence to any operationId encountered in the specification. It will also respect x-router-controller. You may import and extend connexion.resolver.Resolver to implement your own operationId (and function) resolution algorithm.
API Versioning and basePath
You can also define a basePath on the top level of the API specification. This is useful for versioned APIs. To serve the previous endpoint from http://MYHOST/1.0/hello_world, type:
basePath: /1.0
paths:
/hello_world:
post:
operationId: myapp.api.hello_world
If you don’t want to include the base path in your specification, you can just provide it when adding the API to your application:
app.add_api('my_api.yaml', base_path='/1.0')
Swagger JSON
Connexion makes the OpenAPI/Swagger specification in JSON format available from swagger.json in the base path of the API.
HTTPS Support
When specifying HTTPS as the scheme in the API YAML file, all the URIs in the served Swagger UI are HTTPS endpoints. The problem: The default server that runs is a “normal” HTTP server. This means that the Swagger UI cannot be used to play with the API. What is the correct way to start a HTTPS server when using Connexion?
One way, described by Flask, looks like this:
from OpenSSL import SSL
context = SSL.Context(SSL.SSLv23_METHOD)
context.use_privatekey_file('yourserver.key')
context.use_certificate_file('yourserver.crt')
app.run(host='127.0.0.1', port='12344',
debug=False/True, ssl_context=context)
However, Connexion doesn’t provide an ssl_context parameter. This is because Flask doesn’t, either—but it uses **kwargs to send the parameters to the underlying werkzeug server.
The Swagger UI Console
The Swagger UI for an API is available, by default, in {base_path}/ui/ where base_path is the base path of the API.
You can disable the Swagger UI at the application level:
app = connexion.App(__name__, specification_dir='swagger/',
swagger_ui=False)
app.add_api('my_api.yaml')
You can also disable it at the API level:
app = connexion.App(__name__, specification_dir='swagger/')
app.add_api('my_api.yaml', swagger_ui=False)
Server Backend
Connexion uses the default Flask server. For asynchronous applications, you can also use Tornado as the HTTP server. To do this, set your server to tornado:
import connexion
app = connexion.App(__name__, specification_dir='swagger/')
app.run(server='tornado', port=8080)
You can use the Flask WSGI app with any WSGI container, e.g. using Flask with uWSGI (this is more common):
app = connexion.App(specification_dir='swagger/')
application = app.app # expose global WSGI application object
Set up and run the installation code:
$ sudo pip3 install uwsgi
$ uwsgi --http :8080 -w app -p 16 # use 16 worker processes
See the uWSGI documentation for more information.
Contributing to Connexion/TODOs
We welcome your ideas, issues, and pull requests — just follow the usual/standard practices.
TODOs
If you’d like to become a more consistent contributor to Connexion, we’d love your help working on these:
Additional ways to handle OAuth 2 authentications
Overriding default validation error message
Documentation (Response handling, Passing arguments to functions, etc)
Check our issues waffle board for more info.
Thank You Thank You
We’d like to thank all of Connexion’s contributors for working on this project, and to Swagger/OpenAPI for their support.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for connexion-1.0.67-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 84049db9948fb2c03d2587258c77edabbc10bdc0052ddc9648c930d0d146fb0a |
|
MD5 | ce53190a29cd5e6e6392c6714b9f0c97 |
|
BLAKE2b-256 | 2ec89efbec9770439cfa86270a07dcb77529ff9710f38fcf5f34f605cc88889e |