mirror of
https://github.com/LukeHagar/connexion.git
synced 2025-12-06 04:19:26 +00:00
Update readme (#1769)
Contributes to #1531 --------- Co-authored-by: Ruwan <ruwan.lambrichts@ml6.eu>
This commit is contained in:
@@ -1,73 +0,0 @@
|
|||||||
Architecture
|
|
||||||
============
|
|
||||||
|
|
||||||
This document describes the high-level architecture of Connexion.
|
|
||||||
|
|
||||||
.. image:: docs/images/architecture.png
|
|
||||||
:width: 800
|
|
||||||
:align: center
|
|
||||||
:alt: Connexion architecture
|
|
||||||
|
|
||||||
Apps
|
|
||||||
----
|
|
||||||
|
|
||||||
A Connexion ``App`` or application wraps a specific framework application (currently Flask) and exposes a standardized interface for users to create and configure their Connexion
|
|
||||||
application.
|
|
||||||
|
|
||||||
While a Connexion app implements the WSGI interface, it only acts ass a pass-through and doesn't
|
|
||||||
actually intercept requests and responses. Connexion does all request and response manipulation
|
|
||||||
by wrapping the user view function in a Connexion ``Operation``. The underlying framework
|
|
||||||
application handles incoming requests and routes them to the correct Connexion ``Operation``.
|
|
||||||
|
|
||||||
Api
|
|
||||||
---
|
|
||||||
|
|
||||||
A connexion ``API`` takes in an OpenAPI specification and translates the operations defined in it to
|
|
||||||
a set of Connexion ``Operations``. This set of operations is implemented as a framework blueprint
|
|
||||||
(A `Flask blueprint`_ or framework-specific equivalent), which can be registered on the framework
|
|
||||||
application.
|
|
||||||
|
|
||||||
For each operation, the ``API`` resolves the user view function to link to the operation, wraps it
|
|
||||||
with a Connexion ``Operation`` which it configures based on the OpenAPI spec, and finally adds it as
|
|
||||||
a route on the framework blueprint.
|
|
||||||
|
|
||||||
When the ``API`` is registered on the Connexion ``APP``, the underlying framework blueprint is
|
|
||||||
registered on the framework app.
|
|
||||||
|
|
||||||
Operations
|
|
||||||
----------
|
|
||||||
|
|
||||||
A Connexion ``Operation`` implements an OpenAPI operation (`swagger 2`_, `OpenAPI 3`_), which
|
|
||||||
describes a single API operation on a path. It wraps the view function linked to the operation with
|
|
||||||
decorators to handle security, validation, serialization etc. based on the OpenAPI specification,
|
|
||||||
and exposes the result to be registered as a route on the application.
|
|
||||||
|
|
||||||
These decorators intercept incoming requests and outgoing responses of the operation and allow
|
|
||||||
Connexion to manipulate them while leaving the routing up to the underlying framework. The split
|
|
||||||
into separate decorators allows for a clean layered implementation of Connexion functionality.
|
|
||||||
|
|
||||||
The result is equivalent to the following user code, but instead Connexion implements this
|
|
||||||
automatically based on the OpenAPI spec.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
@request_response_lifecycle
|
|
||||||
@secure_endpoint
|
|
||||||
@validate_inputs
|
|
||||||
@deserialize_function_inputs
|
|
||||||
@serialize_function_outputs
|
|
||||||
@validate_outputs
|
|
||||||
def user_provided_view_function():
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
Connexion requests and responses
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
Connexion defines a request and response interface for internal use. The outermost decorator of
|
|
||||||
the operation casts framework specific requests to ``ConnexionRequests`` and ``ConnexionResponses``
|
|
||||||
to framework specific responses.
|
|
||||||
|
|
||||||
.. _Flask blueprint: https://flask.palletsprojects.com/en/2.0.x/blueprints/
|
|
||||||
.. _swagger 2: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/2.0.md#operation-object
|
|
||||||
.. _OpenAPI 3: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.0.md#operationObject
|
|
||||||
827
README.rst
827
README.rst
@@ -1,63 +1,63 @@
|
|||||||
Connexion
|
.. raw:: html
|
||||||
=========
|
|
||||||
|
|
||||||
.. image:: https://badges.gitter.im/zalando/connexion.svg
|
<a id="top"></a>
|
||||||
:alt: Join the chat at https://gitter.im/zalando/connexion
|
<p align="center">
|
||||||
:target: https://gitter.im/zalando/connexion?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
<img src="docs/images/logo_banner.svg" width="100%"/>
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://pypi.org/project/connexion"><img alt="coveralls" src="https://img.shields.io/pypi/status/connexion.svg?style=flat-square&color=brightgreen"></a>
|
||||||
|
<a href="https://pypi.org/project/connexion"><img alt="PyPI version" src="https://img.shields.io/pypi/v/connexion?color=brightgreen&style=flat-square"></a>
|
||||||
|
<a href="https://github.com/spec-first/connexion/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/connexion?style=flat-square&color=brightgreen"></a>
|
||||||
|
<a href="https://github.com/spec-first/connexion/actions/workflows/pipeline.yml"><img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/spec-first/connexion/pipeline.yml?style=flat-square"></a>
|
||||||
|
<a href="https://coveralls.io/github/spec-first/connexion?branch=main"><img alt="Coveralls" src="https://img.shields.io/coverallsCoverage/github/spec-first/connexion?style=flat-square"></a>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
<a href="https://connexion.readthedocs.io/en/stable/"><strong>Explore the docs »</strong></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
.. image:: https://github.com/zalando/connexion/actions/workflows/pipeline.yml/badge.svg
|
----
|
||||||
:alt: Build status
|
|
||||||
:target: https://github.com/zalando/connexion/actions/workflows/pipeline.yml
|
|
||||||
|
|
||||||
.. image:: https://coveralls.io/repos/github/zalando/connexion/badge.svg?branch=main
|
Connexion is a modern Python web framework that makes spec-first and api-first development easy.
|
||||||
:target: https://coveralls.io/github/zalando/connexion?branch=main
|
You describe your API in an `OpenAPI`_ (or `Swagger`_) specification with as much detail as you
|
||||||
:alt: Coveralls status
|
want and Connexion will guarantee that it works as you specified.
|
||||||
|
|
||||||
.. image:: https://img.shields.io/pypi/v/connexion.svg
|
It works either standalone, or in combination with any ASGI or WSGI-compatible framework!
|
||||||
:target: https://pypi.python.org/pypi/connexion
|
|
||||||
:alt: Latest Version
|
|
||||||
|
|
||||||
.. image:: https://img.shields.io/pypi/status/connexion.svg
|
.. raw:: html
|
||||||
:target: https://pypi.python.org/pypi/connexion
|
|
||||||
:alt: Development Status
|
|
||||||
|
|
||||||
.. image:: https://img.shields.io/pypi/pyversions/connexion.svg
|
<p align="center">
|
||||||
:target: https://pypi.python.org/pypi/connexion
|
<br>
|
||||||
:alt: Python Versions
|
<a href="https://connexion.readthedocs.io/en/latest/v3.html"><strong>📢 Connexion 3 was recently released! Read about the changes here »</strong></a>
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
</p>
|
||||||
|
|
||||||
.. image:: https://img.shields.io/pypi/l/connexion.svg
|
|
||||||
:target: https://github.com/zalando/connexion/blob/main/LICENSE.txt
|
|
||||||
:alt: License
|
|
||||||
|
|
||||||
Connexion is a framework that automagically handles HTTP requests based on `OpenAPI Specification`_
|
✨ Features
|
||||||
(formerly known as Swagger Spec) of your API described in `YAML format`_. Connexion allows you to
|
===========
|
||||||
write an OpenAPI specification, then maps the endpoints to your Python functions; this makes it
|
|
||||||
unique, as many tools generate the specification based on your Python code. You can describe your
|
|
||||||
REST API in as much detail as you want; then Connexion guarantees that it will work as you
|
|
||||||
specified.
|
|
||||||
|
|
||||||
We built Connexion this way in order to:
|
Connexion provides the following functionality **based on your specification**:
|
||||||
|
|
||||||
- simplify the development process
|
- 🚏 **Automatic route registration**, no ``@route`` decorators needed
|
||||||
- confirm expectations about what your API will look like
|
- 🔒 **Authentication**, split from your application logic
|
||||||
|
- 🔎 **Request and response validation** of headers, parameters, and body
|
||||||
|
- 📬 **Parameter parsing and injection**, no request object needed
|
||||||
|
- 📨 **Response serialization**, you can return regular Python objects
|
||||||
|
- 📺 **A Swagger UI console** with live documentation and ‘try it out’ feature
|
||||||
|
- 🧩 **Pluggability**, in all dimensions
|
||||||
|
|
||||||
Connexion Features:
|
Connexion also **helps you write your OpenAPI specification** and develop against it by providing a command line interface which lets you test and mock your specification.
|
||||||
-------------------
|
|
||||||
|
|
||||||
- Validates requests and endpoint parameters automatically, based on
|
.. code-block:: bash
|
||||||
your specification
|
|
||||||
- Provides a Web Swagger Console UI so that the users of your API can
|
|
||||||
have 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
|
connexion run openapi.yaml
|
||||||
-------------
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
|
🪤 Why Connexion
|
||||||
|
================
|
||||||
|
|
||||||
With Connexion, you write the spec first. Connexion then calls your Python
|
With Connexion, you write the spec first. Connexion then calls your Python
|
||||||
code, handling the mapping from the specification to the code. This
|
code, handling the mapping from the specification to the code. This
|
||||||
@@ -65,520 +65,209 @@ incentivizes you to write the specification so that all of your
|
|||||||
developers can understand what your API does, even before you write a
|
developers can understand what your API does, even before you write a
|
||||||
single line of code.
|
single line of code.
|
||||||
|
|
||||||
If multiple teams depend on your APIs, you can use Connexion to easily send them the documentation of your API. This guarantees that your API will follow the specification that you wrote. This is a different process from that offered by frameworks such as Hug_, which generates a specification *after* you've written the code. Some disadvantages of generating specifications based on code is that they often end up lacking details or mix your documentation with the code logic of your application.
|
If multiple teams depend on your APIs, you can use Connexion to easily
|
||||||
|
send them the documentation of your API. This guarantees that your API will
|
||||||
|
follow the specification that you wrote. This is a different process from
|
||||||
|
the one offered by most frameworks, which generate a specification
|
||||||
|
*after* you've written the code.
|
||||||
|
Some disadvantages of generating specifications based on code is that
|
||||||
|
they often end up lacking details or mix your documentation with the implementation
|
||||||
|
logic of your application.
|
||||||
|
|
||||||
Other Sources/Mentions
|
.. raw:: html
|
||||||
----------------------
|
|
||||||
|
|
||||||
- Zalando RESTful API guidelines with `API First`_
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
- Connexion listed on Swagger_'s website
|
|
||||||
- Blog post: `Crafting effective Microservices in Python`_
|
|
||||||
|
|
||||||
New in Connexion 2.0:
|
⚒️ How to Use
|
||||||
---------------------
|
=============
|
||||||
- App and Api options must be provided through the "options" argument (``old_style_options`` have been removed).
|
|
||||||
- You must specify a form content-type in 'consumes' in order to consume form data.
|
|
||||||
- The `Operation` interface has been formalized in the `AbstractOperation` class.
|
|
||||||
- The `Operation` class has been renamed to `Swagger2Operation`.
|
|
||||||
- Array parameter deserialization now follows the Swagger 2.0 spec more closely.
|
|
||||||
In situations when a query parameter is passed multiple times, and the collectionFormat is either csv or pipes, the right-most value will be used.
|
|
||||||
For example, `?q=1,2,3&q=4,5,6` will result in `q = [4, 5, 6]`.
|
|
||||||
The old behavior is available by setting the collectionFormat to `multi`, or by importing `decorators.uri_parsing.AlwaysMultiURIParser` and passing `parser_class=AlwaysMultiURIParser` to your Api.
|
|
||||||
- The spec validator library has changed from `swagger-spec-validator` to `openapi-spec-validator`.
|
|
||||||
- Errors that previously raised `SwaggerValidationError` now raise the `InvalidSpecification` exception.
|
|
||||||
All spec validation errors should be wrapped with `InvalidSpecification`.
|
|
||||||
- Support for nullable/x-nullable, readOnly and writeOnly/x-writeOnly has been added to the standard json schema validator.
|
|
||||||
- Custom validators can now be specified on api level (instead of app level).
|
|
||||||
- Added support for basic authentication and apikey authentication
|
|
||||||
- If unsupported security requirements are defined or ``x-tokenInfoFunc``/``x-tokenInfoUrl`` is missing, connexion now denies requests instead of allowing access without security-check.
|
|
||||||
- Accessing ``connexion.request.user`` / ``flask.request.user`` is no longer supported, use ``connexion.context['user']`` instead
|
|
||||||
|
|
||||||
How to Use
|
Installation
|
||||||
==========
|
------------
|
||||||
|
|
||||||
Prerequisites
|
You can install connexion using pip:
|
||||||
-------------
|
|
||||||
|
|
||||||
Python 3.6+
|
|
||||||
|
|
||||||
Installing It
|
|
||||||
-------------
|
|
||||||
|
|
||||||
In your command line, type:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ pip install connexion
|
$ pip install connexion
|
||||||
|
|
||||||
Running It
|
Connexion provides 'extras' with optional dependencies to unlock additional features:
|
||||||
----------
|
|
||||||
|
|
||||||
Place your API YAML inside a folder in the root
|
- ``swagger-ui``: Enables a Swagger UI console for your application.
|
||||||
path of your application (e.g ``swagger/``). Then run:
|
- ``uvicorn``: Enables to run the your application using :code:`app.run()` for
|
||||||
|
development instead of using an external ASGI server.
|
||||||
|
- ``flask``: Enables the ``FlaskApp`` to build applications compatible with the Flask
|
||||||
|
ecosystem.
|
||||||
|
|
||||||
.. code-block:: python
|
You can install them as follows:
|
||||||
|
|
||||||
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 to run and use Connexion!
|
|
||||||
|
|
||||||
|
|
||||||
OAuth 2 Authentication and Authorization
|
|
||||||
----------------------------------------
|
|
||||||
|
|
||||||
Connexion supports one of the three OAuth 2 handling methods. (See
|
|
||||||
"TODO" below.) With Connexion, the API security definition **must**
|
|
||||||
include a 'x-tokenInfoUrl' or 'x-tokenInfoFunc (or set ``TOKENINFO_URL``
|
|
||||||
or ``TOKENINFO_FUNC`` env var respectively). 'x-tokenInfoUrl' must contain an
|
|
||||||
URL to validate and get the `token information`_ and 'x-tokenInfoFunc must
|
|
||||||
contain a reference to a function used to obtain the token info. When both 'x-tokenInfoUrl'
|
|
||||||
and 'x-tokenInfoFunc' are used, Connexion will prioritize the function method. Connexion expects to
|
|
||||||
receive the OAuth token in the ``Authorization`` header field in the
|
|
||||||
format described in `RFC 6750 <rfc6750_>`_ section 2.1. This aspect
|
|
||||||
represents a significant difference from the usual OAuth flow.
|
|
||||||
|
|
||||||
Dynamic Rendering of Your Specification
|
|
||||||
---------------------------------------
|
|
||||||
|
|
||||||
Connexion uses Jinja2_ to allow specification parameterization through the ``arguments`` parameter. You can define specification arguments for the application either globally (via the ``connexion.App`` constructor) or for each specific API (via the ``connexion.App#add_api`` method):
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
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**:
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
paths:
|
|
||||||
/hello_world:
|
|
||||||
post:
|
|
||||||
operationId: myapp.api.hello_world
|
|
||||||
|
|
||||||
If you provide this path in your specification POST requests to
|
|
||||||
``http://MYHOST/hello_world``, it will be handled by the function
|
|
||||||
``hello_world`` in the ``myapp.api`` module. Optionally, you can include
|
|
||||||
``x-swagger-router-controller`` (or ``x-openapi-router-controller``) in your
|
|
||||||
operation definition, making ``operationId`` relative:
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
paths:
|
|
||||||
/hello_world:
|
|
||||||
post:
|
|
||||||
x-swagger-router-controller: myapp.api
|
|
||||||
operationId: hello_world
|
|
||||||
|
|
||||||
Keep in mind that Connexion follows how `HTTP methods work in Flask`_ and therefore HEAD requests will be handled by the ``operationId`` specified under GET in the specification. If both methods are supported, ``connexion.request.method`` can be used to determine which request was made.
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from connexion.resolver import RestyResolver
|
|
||||||
|
|
||||||
app = connexion.App(__name__)
|
|
||||||
app.add_api('swagger.yaml', resolver=RestyResolver('api'))
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
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.put
|
|
||||||
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 can import and extend ``connexion.resolver.Resolver`` to implement your own ``operationId``
|
|
||||||
(and function) resolution algorithm.
|
|
||||||
|
|
||||||
Automatic Parameter Handling
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
Connexion automatically maps the parameters defined in your endpoint specification to arguments of your Python views as named parameters, and, whenever possible, with value casting. Simply define the endpoint's parameters with the same names as your views arguments.
|
|
||||||
|
|
||||||
As an example, say you have an endpoint specified as:
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
paths:
|
|
||||||
/foo:
|
|
||||||
get:
|
|
||||||
operationId: api.foo_get
|
|
||||||
parameters:
|
|
||||||
- name: message
|
|
||||||
description: Some message.
|
|
||||||
in: query
|
|
||||||
type: string
|
|
||||||
required: true
|
|
||||||
|
|
||||||
And the view function:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
# api.py file
|
|
||||||
|
|
||||||
def foo_get(message):
|
|
||||||
# do something
|
|
||||||
return 'You send the message: {}'.format(message), 200
|
|
||||||
|
|
||||||
In this example, Connexion automatically recognizes that your view
|
|
||||||
function expects an argument named ``message`` and assigns the value
|
|
||||||
of the endpoint parameter ``message`` to your view function.
|
|
||||||
|
|
||||||
.. note:: In the OpenAPI 3.x.x spec, the requestBody does not have a name.
|
|
||||||
By default it will be passed in as 'body'. You can optionally
|
|
||||||
provide the x-body-name parameter in your requestBody
|
|
||||||
(or legacy position within the requestBody schema)
|
|
||||||
to override the name of the parameter that will be passed to your
|
|
||||||
handler function.
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
|
|
||||||
/path
|
|
||||||
post:
|
|
||||||
requestBody:
|
|
||||||
x-body-name: body
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
# legacy location here should be ignored because the preferred location for x-body-name is at the requestBody level above
|
|
||||||
x-body-name: this_should_be_ignored
|
|
||||||
$ref: '#/components/schemas/someComponent'
|
|
||||||
|
|
||||||
.. warning:: When you define a parameter at your endpoint as *not* required, and
|
|
||||||
this argument does not have default value in your Python view, you will get
|
|
||||||
a "missing positional argument" exception whenever you call this endpoint
|
|
||||||
WITHOUT the parameter. Provide a default value for a named argument or use
|
|
||||||
``**kwargs`` dict.
|
|
||||||
|
|
||||||
Type casting
|
|
||||||
^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Whenever possible, Connexion will try to parse your argument values and
|
|
||||||
do type casting to related Python native values. The current
|
|
||||||
available type castings are:
|
|
||||||
|
|
||||||
+--------------+-------------+
|
|
||||||
| OpenAPI Type | Python Type |
|
|
||||||
+==============+=============+
|
|
||||||
| integer | int |
|
|
||||||
+--------------+-------------+
|
|
||||||
| string | str |
|
|
||||||
+--------------+-------------+
|
|
||||||
| number | float |
|
|
||||||
+--------------+-------------+
|
|
||||||
| boolean | bool |
|
|
||||||
+--------------+-------------+
|
|
||||||
| array | list |
|
|
||||||
+--------------+-------------+
|
|
||||||
| null | None |
|
|
||||||
+--------------+-------------+
|
|
||||||
| object | dict |
|
|
||||||
+--------------+-------------+
|
|
||||||
|
|
||||||
If you use the ``array`` type In the Swagger definition, you can define the
|
|
||||||
``collectionFormat`` so that it won't be recognized. Connexion currently
|
|
||||||
supports collection formats "pipes" and "csv". The default format is "csv".
|
|
||||||
|
|
||||||
Connexion is opinionated about how the URI is parsed for ``array`` types.
|
|
||||||
The default behavior for query parameters that have been defined multiple
|
|
||||||
times is to use the right-most value. For example, if you provide a URI with
|
|
||||||
the query string ``?letters=a,b,c&letters=d,e,f``, connexion will set
|
|
||||||
``letters = ['d', 'e', 'f']``.
|
|
||||||
|
|
||||||
You can override this behavior by specifying the URI parser in the app or
|
|
||||||
api options.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from connexion.decorators.uri_parsing import AlwaysMultiURIParser
|
|
||||||
options = {'uri_parser_class': AlwaysMultiURIParser}
|
|
||||||
app = connexion.App(__name__, specification_dir='swagger/', options=options)
|
|
||||||
|
|
||||||
You can implement your own URI parsing behavior by inheriting from
|
|
||||||
``connexion.decorators.uri_parsing.AbstractURIParser``.
|
|
||||||
|
|
||||||
There are a handful of URI parsers included with connection.
|
|
||||||
|
|
||||||
+----------------------+---------------------------------------------------------------------------+
|
|
||||||
| OpenAPIURIParser | This parser adheres to the OpenAPI 3.x.x spec, and uses the ``style`` |
|
|
||||||
| default: OpenAPI 3.0 | parameter. Query parameters are parsed from left to right, so if a query |
|
|
||||||
| | parameter is defined twice, then the right-most definition will take |
|
|
||||||
| | precedence. For example, if you provided a URI with the query string |
|
|
||||||
| | ``?letters=a,b,c&letters=d,e,f``, and ``style: simple``, then connexion |
|
|
||||||
| | will set ``letters = ['d', 'e', 'f']``. For additional information see |
|
|
||||||
| | `OpenAPI 3.0 Style Values`_. |
|
|
||||||
+----------------------+---------------------------------------------------------------------------+
|
|
||||||
| Swagger2URIParser | This parser adheres to the Swagger 2.0 spec, and will only join together |
|
|
||||||
| default: OpenAPI 2.0 | multiple instance of the same query parameter if the ``collectionFormat`` |
|
|
||||||
| | is set to ``multi``. Query parameters are parsed from left to right, so |
|
|
||||||
| | if a query parameter is defined twice, then the right-most definition |
|
|
||||||
| | wins. For example, if you provided a URI with the query string |
|
|
||||||
| | ``?letters=a,b,c&letters=d,e,f``, and ``collectionFormat: csv``, then |
|
|
||||||
| | connexion will set ``letters = ['d', 'e', 'f']`` |
|
|
||||||
+----------------------+---------------------------------------------------------------------------+
|
|
||||||
| FirstValueURIParser | This parser behaves like the Swagger2URIParser, except that it prefers |
|
|
||||||
| | the first defined value. For example, if you provided a URI with the query|
|
|
||||||
| | string ``?letters=a,b,c&letters=d,e,f`` and ``collectionFormat: csv`` |
|
|
||||||
| | hen connexion will set ``letters = ['a', 'b', 'c']`` |
|
|
||||||
+----------------------+---------------------------------------------------------------------------+
|
|
||||||
| AlwaysMultiURIParser | This parser is backwards compatible with Connexion 1.x. It joins together |
|
|
||||||
| | multiple instances of the same query parameter. |
|
|
||||||
+----------------------+---------------------------------------------------------------------------+
|
|
||||||
|
|
||||||
|
|
||||||
Parameter validation
|
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Connexion can apply strict parameter validation for query and form data
|
|
||||||
parameters. When this is enabled, requests that include parameters not defined
|
|
||||||
in the swagger spec return a 400 error. You can enable it when adding the API
|
|
||||||
to your application:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
app.add_api('my_apy.yaml', strict_validation=True)
|
|
||||||
|
|
||||||
API Versioning and basePath
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
Setting a base path is useful for versioned APIs. An example of
|
|
||||||
a base path would be the ``1.0`` in ``http://MYHOST/1.0/hello_world``.
|
|
||||||
|
|
||||||
If you are using OpenAPI 3.x.x, you set your base URL path in the
|
|
||||||
servers block of the specification. You can either specify a full
|
|
||||||
URL, or just a relative path.
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
servers:
|
|
||||||
- url: https://MYHOST/1.0
|
|
||||||
description: full url example
|
|
||||||
- url: /1.0
|
|
||||||
description: relative path example
|
|
||||||
|
|
||||||
paths:
|
|
||||||
...
|
|
||||||
|
|
||||||
If you are using OpenAPI 2.0, you can define a ``basePath`` on the top level
|
|
||||||
of your OpenAPI 2.0 specification.
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
basePath: /1.0
|
|
||||||
|
|
||||||
paths:
|
|
||||||
...
|
|
||||||
|
|
||||||
If you don't want to include the base path in your specification, you
|
|
||||||
can provide it when adding the API to your application:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
app.add_api('my_api.yaml', base_path='/1.0')
|
|
||||||
|
|
||||||
Swagger JSON
|
|
||||||
------------
|
|
||||||
Connexion makes the OpenAPI/Swagger specification in JSON format
|
|
||||||
available from either ``swagger.json`` (for OpenAPI 2.0) or
|
|
||||||
``openapi.json`` (for OpenAPI 3.x.x) at the base path of the API.
|
|
||||||
For example, if your base path was ``1.0``, then your spec would be
|
|
||||||
available at ``/1.0/openapi.json``.
|
|
||||||
|
|
||||||
You can disable serving the spec JSON at the application level:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
options = {"serve_spec": False}
|
|
||||||
app = connexion.App(__name__, specification_dir='openapi/',
|
|
||||||
options=options)
|
|
||||||
app.add_api('my_api.yaml')
|
|
||||||
|
|
||||||
You can also disable it at the API level:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
options = {"serve_spec": False}
|
|
||||||
app = connexion.App(__name__, specification_dir='openapi/')
|
|
||||||
app.add_api('my_api.yaml', options=options)
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
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 through pip extras.
|
|
||||||
You can install it with ``pip install connexion[swagger-ui]``.
|
|
||||||
It will be served up at ``{base_path}/ui/`` where ``base_path`` is the
|
|
||||||
base path of the API.
|
|
||||||
|
|
||||||
You can disable the Swagger UI at the application level:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
app = connexion.App(__name__, specification_dir='openapi/',
|
|
||||||
options={"swagger_ui": False})
|
|
||||||
app.add_api('my_api.yaml')
|
|
||||||
|
|
||||||
|
|
||||||
You can also disable it at the API level:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
app = connexion.App(__name__, specification_dir='openapi/')
|
|
||||||
app.add_api('my_api.yaml', options={"swagger_ui": False})
|
|
||||||
|
|
||||||
If necessary, you can explicitly specify the path to the directory with
|
|
||||||
swagger-ui to not use the connexion[swagger-ui] distro.
|
|
||||||
In order to do this, you should specify the following option:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
options = {'swagger_path': '/path/to/swagger_ui/'}
|
|
||||||
app = connexion.App(__name__, specification_dir='openapi/', options=options)
|
|
||||||
|
|
||||||
If you wish to provide your own swagger-ui distro, note that connexion
|
|
||||||
expects a jinja2 file called ``swagger_ui/index.j2`` in order to load the
|
|
||||||
correct ``swagger.json`` by default. Your ``index.j2`` file can use the
|
|
||||||
``openapi_spec_url`` jinja variable for this purpose:
|
|
||||||
|
|
||||||
.. code-block::
|
|
||||||
|
|
||||||
const ui = SwaggerUIBundle({ url: "{{ openapi_spec_url }}"})
|
|
||||||
|
|
||||||
Additionally, if you wish to use swagger-ui-3.x.x, it is also provided by
|
|
||||||
installing connexion[swagger-ui], and can be enabled like this:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from swagger_ui_bundle import swagger_ui_3_path
|
|
||||||
options = {'swagger_path': swagger_ui_3_path}
|
|
||||||
app = connexion.App(__name__, specification_dir='swagger/', options=options)
|
|
||||||
|
|
||||||
|
|
||||||
Server Backend
|
|
||||||
--------------
|
|
||||||
|
|
||||||
By default Connexion uses the Flask_ server. For asynchronous
|
|
||||||
applications, you can also use Tornado_ as the HTTP server. To do
|
|
||||||
this, set your server to ``tornado``:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
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 common):
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
app = connexion.App(__name__, specification_dir='swagger/')
|
|
||||||
application = app.app # expose global WSGI application object
|
|
||||||
|
|
||||||
You can use the ``aiohttp`` framework as server backend as well:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
import connexion
|
|
||||||
|
|
||||||
app = connexion.AioHttpApp(__name__, specification_dir='swagger/')
|
|
||||||
app.run(port=8080)
|
|
||||||
|
|
||||||
.. note:: Also check aiohttp handler examples_.
|
|
||||||
|
|
||||||
Set up and run the installation code:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ sudo pip3 install uwsgi
|
$ pip install connexion[swagger-ui]
|
||||||
$ uwsgi --http :8080 -w app -p 16 # use 16 worker processes
|
$ pip install connexion[swagger-ui,uvicorn].
|
||||||
|
|
||||||
See the `uWSGI documentation`_ for more information.
|
.. raw:: html
|
||||||
|
|
||||||
.. _using Flask with uWSGI: http://flask.pocoo.org/docs/latest/deploying/uwsgi/
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
.. _uWSGI documentation: https://uwsgi-docs.readthedocs.org/
|
|
||||||
.. _examples: https://docs.aiohttp.org/en/stable/web.html#handler
|
|
||||||
|
|
||||||
|
|
||||||
Documentation
|
Creating your application
|
||||||
=============
|
-------------------------
|
||||||
Additional information is available at `Connexion's Documentation Page`_.
|
|
||||||
|
|
||||||
Changes
|
Connexion can be used either as a standalone application or as a middleware wrapping an existing
|
||||||
=======
|
ASGI (or WSGI) application written using a different framework. The standalone application can be
|
||||||
|
built using either the :code:`AsyncApp` or :code:`FlaskApp`.
|
||||||
|
|
||||||
|
- The :code:`AsyncApp` is a lightweight application with native asynchronous support. Use it if you
|
||||||
|
are starting a new project and have no specific reason to use one of the other options.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from connexion import AsyncApp
|
||||||
|
|
||||||
|
app = AsyncApp(__name__)
|
||||||
|
|
||||||
|
- The :code:`FlaskApp` leverages the `Flask` framework, which is useful if you're migrating from
|
||||||
|
connexion 2.X or you want to leverage the `Flask` ecosystem.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from connexion import FlaskApp
|
||||||
|
|
||||||
|
app = FlaskApp(__name__)
|
||||||
|
|
||||||
|
- The :code:`ConnexionMiddleware` can be wrapped around any existing ASGI or WSGI application.
|
||||||
|
Use it if you already have an application written in a different framework and want to add
|
||||||
|
functionality provided by connexion
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from asgi_framework import App
|
||||||
|
from connexion import ConnexionMiddleware
|
||||||
|
|
||||||
|
app = App(__name__)
|
||||||
|
app = ConnexionMiddleware(app)
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
|
Registering an API
|
||||||
|
------------------
|
||||||
|
|
||||||
|
While you can register individual routes on your application, Connexion really shines when you
|
||||||
|
register an API defined by an OpenAPI (or Swagger) specification.
|
||||||
|
The operation described in your specification is automatically linked to your Python view function via the ``operationId``
|
||||||
|
|
||||||
|
**run.py**
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def post_greeting(name: str, greeting: str): # Paramaeters are automatically unpacked
|
||||||
|
return f"{greeting} {name}", 200 # Responses are automatically serialized
|
||||||
|
|
||||||
|
app.add_api("openapi.yaml")
|
||||||
|
|
||||||
|
**openapi.yaml**
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
...
|
||||||
|
paths:
|
||||||
|
/greeting/{name}:
|
||||||
|
post:
|
||||||
|
operationId: run.post_greeting
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
content:
|
||||||
|
text/plain:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
parameters:
|
||||||
|
- name: name
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: greeting
|
||||||
|
in: query
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
|
Running your application
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
If you installed connexion using :code:`connexion[uvicorn]`, you can run it using the
|
||||||
|
:code:`run` method. This is only recommended for development:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
app.run()
|
||||||
|
|
||||||
|
In production, run your application using an ASGI server such as `uvicorn`. If you defined your
|
||||||
|
:code:`app` in a python module called :code:`run.py`, you can run it as follows:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ uvicorn run:app
|
||||||
|
|
||||||
|
Or with gunicorn:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ gunicorn -k uvicorn.workers.UvicornWorker run:app
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
Now you're able to run and use Connexion!
|
||||||
|
|
||||||
|
See the `examples`_ folder for more examples.
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
|
🙏 Thanks
|
||||||
|
=========
|
||||||
|
|
||||||
|
We'd like to thank all of Connexion's contributors for working on this
|
||||||
|
project, Swagger/OpenAPI for their support, and Zalando for originally developing and releasing Connexion.
|
||||||
|
|
||||||
|
Sponsors
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. image:: ./docs/images/sponsors/ML6.png
|
||||||
|
:alt: GitHub Sponsors
|
||||||
|
:target: https://www.ml6.eu
|
||||||
|
|
||||||
|
|
|
||||||
|
Sponsors help us dedicate time to maintain Connexion. Want to help?
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<a href="https://github.com/sponsors/spec-first"><strong>Explore the options »</strong></a>
|
||||||
|
|
||||||
|
.. raw:: html
|
||||||
|
|
||||||
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
|
📜 Changes
|
||||||
|
==========
|
||||||
|
|
||||||
A full changelog is maintained on the `GitHub releases page`_.
|
A full changelog is maintained on the `GitHub releases page`_.
|
||||||
|
|
||||||
.. _GitHub releases page: https://github.com/zalando/connexion/releases
|
.. _GitHub releases page: https://github.com/spec-first/connexion/releases
|
||||||
|
|
||||||
Contributing to Connexion/TODOs
|
.. raw:: html
|
||||||
===============================
|
|
||||||
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
|
🤲 Contributing
|
||||||
|
===============
|
||||||
|
|
||||||
We welcome your ideas, issues, and pull requests. Just follow the
|
We welcome your ideas, issues, and pull requests. Just follow the
|
||||||
usual/standard GitHub practices.
|
usual/standard GitHub practices.
|
||||||
@@ -588,59 +277,47 @@ install the pre-commit hooks to automatically run black formatting and static an
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
|
pip install poetry
|
||||||
poetry install --all-extras
|
poetry install --all-extras
|
||||||
pre-commit install
|
pre-commit install
|
||||||
|
|
||||||
You can find out more about how Connexion works and where to apply your changes by having a look
|
You can find out more about how Connexion works and where to apply your changes by having a look
|
||||||
at our `ARCHITECTURE.rst <ARCHITECTURE.rst>`_.
|
at our `architecture <./docs/images/architecture.png>`_.
|
||||||
|
|
||||||
Unless you explicitly state otherwise in advance, any non trivial
|
Unless you explicitly state otherwise in advance, any non trivial
|
||||||
contribution intentionally submitted for inclusion in this project by you
|
contribution intentionally submitted for inclusion in this project by you
|
||||||
to the steward of this repository (Zalando SE, Berlin) shall be under the
|
to the steward of this repository shall be under the
|
||||||
terms and conditions of Apache License 2.0 written below, without any
|
terms and conditions of Apache License 2.0 written below, without any
|
||||||
additional copyright information, terms or conditions.
|
additional copyright information, terms or conditions.
|
||||||
|
|
||||||
TODOs
|
.. raw:: html
|
||||||
-----
|
|
||||||
|
|
||||||
|
<p align="right">(<a href="#top">back to top</a>)</p>
|
||||||
|
|
||||||
If you'd like to become a more consistent contributor to Connexion, we'd love your help working on
|
📚 Recommended Resources
|
||||||
these we have a list of `issues where we are looking for contributions`_.
|
========================
|
||||||
|
|
||||||
Thanks
|
About the advantages of working spec-first:
|
||||||
===================
|
|
||||||
|
|
||||||
We'd like to thank all of Connexion's contributors for working on this
|
* `Blog Atlassian`_
|
||||||
project, and to Swagger/OpenAPI for their support.
|
* `API guidelines Zalando`_
|
||||||
|
* `Blog ML6`_
|
||||||
|
* `Blog Zalando`_
|
||||||
|
|
||||||
License
|
Tools to help you work spec-first:
|
||||||
===================
|
|
||||||
|
|
||||||
Copyright 2015 Zalando SE
|
* `Online swagger editor`_
|
||||||
|
* `VS Code plugin`_
|
||||||
|
* `Pycharm plugin`_
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
|
.. _v3 documentation: https://connexion.readthedocs.io/en/latest/v3.html
|
||||||
|
.. _OpenAPI: https://openapis.org/
|
||||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
||||||
|
|
||||||
.. _Flask: http://flask.pocoo.org/
|
|
||||||
.. _issues waffle board: https://waffle.io/zalando/connexion
|
|
||||||
.. _API First: https://opensource.zalando.com/restful-api-guidelines/#api-first
|
|
||||||
.. _Hug: https://github.com/timothycrosley/hug
|
|
||||||
.. _Swagger: http://swagger.io/open-source-integrations/
|
.. _Swagger: http://swagger.io/open-source-integrations/
|
||||||
.. _Jinja2: http://jinja.pocoo.org/
|
.. _Blog atlassian: https://www.atlassian.com/blog/technology/spec-first-api-development
|
||||||
.. _rfc6750: https://tools.ietf.org/html/rfc6750
|
.. _Blog ML6: https://blog.ml6.eu/why-we-decided-to-help-maintain-connexion-c9f449877083
|
||||||
.. _OpenAPI Specification: https://www.openapis.org/
|
.. _Blog Zalando: https://engineering.zalando.com/posts/2016/12/crafting-effective-microservices-in-python.html
|
||||||
.. _OpenAPI 3.0 Style Values: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#style-values
|
.. _API guidelines Zalando: https://opensource.zalando.com/restful-api-guidelines/#api-first
|
||||||
.. _Operation Object: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#operation-object
|
.. _Online swagger editor: https://editor.swagger.io/
|
||||||
.. _swager.spec.security_definition: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#security-definitions-object
|
.. _VS Code plugin: https://marketplace.visualstudio.com/items?itemName=42Crunch.vscode-openapi
|
||||||
.. _swager.spec.security_requirement: https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#security-requirement-object
|
.. _Pycharm plugin: https://plugins.jetbrains.com/plugin/14837-openapi-swagger-editor
|
||||||
.. _YAML format: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#format
|
.. _examples: ./examples
|
||||||
.. _token information: https://tools.ietf.org/html/rfc6749
|
|
||||||
.. _Tornado: http://www.tornadoweb.org/en/stable/
|
|
||||||
.. _Connexion Pet Store Example Application: https://github.com/hjacobs/connexion-example
|
|
||||||
.. _described by Flask: http://flask.pocoo.org/snippets/111/
|
|
||||||
.. _werkzeug: http://werkzeug.pocoo.org/
|
|
||||||
.. _Connexion's Documentation Page: http://connexion.readthedocs.org/en/latest/
|
|
||||||
.. _Crafting effective Microservices in Python: https://jobs.zalando.com/tech/blog/crafting-effective-microservices-in-python/
|
|
||||||
.. _issues where we are looking for contributions: https://github.com/zalando/connexion/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22
|
|
||||||
.. _HTTP Methods work in Flask: http://flask.pocoo.org/docs/1.0/quickstart/#http-methods
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 8.9 MiB After Width: | Height: | Size: 1.7 MiB |
7
docs/images/logo_banner.svg
Normal file
7
docs/images/logo_banner.svg
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="508.3" height="102.088" class="css-1j8o68f" viewBox="-31.727 -39.798 382.668 131.629">
|
||||||
|
<path d="M-32.988-41.456h385.411V93.238H-32.988V-41.456Z" style="stroke:#000;fill-rule:nonzero;paint-order:fill;fill:#64b65b;stroke-opacity:0"/>
|
||||||
|
<path fill="#405082" d="m61.624 63.758-1.273-3.613h-7.357l-1.273 3.613H48l6.448-17.515h4.449l6.448 17.515h-3.72zm-7.564-6.655h5.224l-2.606-7.43zm21.2-10.86c3.43 0 5.563 2.545 5.563 5.66 0 3.188-2.133 5.576-5.563 5.576h-3.65v6.279h-3.636V46.243h7.285zm-.606 8.193c1.818 0 2.666-1.006 2.666-2.581 0-1.516-.848-2.57-2.666-2.57H71.61v5.151h3.043zm9.224 9.322V46.243h3.636v17.515h-3.636zm7.66-4.994v-2.921h8.691v2.92h-8.69zm23.054-9.321h-6.666v3.975h5.757v3.164h-5.757v7.176h-3.661V46.243h10.327v3.2zm3.104 14.315V46.243h3.636v17.515h-3.636zm17.406 0-4.558-7.71h-1.054v7.71h-3.637V46.243h6.352c3.963 0 5.636 2.34 5.636 5.236 0 2.352-1.333 3.88-3.71 4.388l5.274 7.891h-4.303zM129.49 49.26v4.182h2.145c1.94 0 2.727-.824 2.727-2.085 0-1.248-.787-2.097-2.727-2.097h-2.145zM147.89 64c-3.758 0-6.691-1.806-7.225-5.09l3.758-.862c.242 1.964 1.685 2.982 3.612 2.982 1.479 0 2.655-.654 2.642-2.133-.012-1.649-1.951-2.17-4.084-2.824-2.57-.8-5.322-1.746-5.322-4.97 0-3.26 2.667-5.103 6.182-5.103 3.08 0 6.182 1.249 6.885 4.606l-3.515.873c-.327-1.746-1.503-2.51-3.152-2.51-1.466 0-2.715.607-2.715 2.05 0 1.345 1.722 1.793 3.71 2.387 2.642.8 5.769 1.818 5.769 5.309 0 3.721-3.115 5.285-6.545 5.285zm20.06-17.757v3.2h-4.157v14.315h-3.6V49.443h-4.182v-3.2h11.94zm19.527 3.2h-6.667v3.975h5.757v3.164h-5.757v7.176h-3.66V46.243h10.327v3.2zM198.337 64c-5.15 0-8.957-3.515-8.957-9.006 0-5.503 3.806-8.994 8.958-8.994 5.139 0 8.945 3.491 8.945 8.994 0 5.49-3.806 9.006-8.945 9.006zm0-3.333c3.019 0 5.334-2.121 5.334-5.673 0-3.54-2.315-5.648-5.333-5.648s-5.334 2.109-5.334 5.648c0 3.552 2.315 5.673 5.334 5.673zm21.54 3.09-4.558-7.708h-1.054v7.709h-3.637V46.243h6.352c3.963 0 5.636 2.34 5.636 5.236 0 2.352-1.333 3.88-3.709 4.388l5.273 7.891h-4.303zm-5.612-14.497v4.182h2.145c1.94 0 2.728-.824 2.728-2.085 0-1.248-.788-2.097-2.728-2.097h-2.145zm30.752 14.498-1.273-3.613h-7.358l-1.272 3.613h-3.721l6.448-17.515h4.448l6.449 17.515h-3.721zm-7.564-6.655h5.224l-2.606-7.43zm17.55 3.442h5.492v3.213h-9.127V46.243h3.636v14.302zm11.904 0h5.49v3.213h-9.126V46.243h3.636v14.302z"/>
|
||||||
|
<path fill="#fff" d="M17.915 36C7.612 36 0 28.994 0 17.988S7.612 0 17.915 0c7.806 0 14.06 4 16.558 10.642l-6.788 2.473c-1.552-4.073-5.26-6.424-9.77-6.424-6.036 0-10.667 4.218-10.667 11.297s4.63 11.32 10.667 11.32c4.51 0 8.218-2.375 9.77-6.448l6.788 2.473C31.976 31.975 25.72 36 17.915 36zm38.036 0c-10.303 0-17.915-7.03-17.915-18.012C38.036 6.982 45.648 0 55.951 0 66.23 0 73.842 6.982 73.842 17.988 73.842 28.97 66.23 36 55.952 36zm0-6.667c6.037 0 10.667-4.242 10.667-11.345 0-7.079-4.63-11.297-10.667-11.297S45.285 10.91 45.285 17.988c0 7.103 4.63 11.345 10.666 11.345zM104.461.486h7.248v35.03h-8.412L87.782 10.472v25.042h-7.249V.485h8.315l15.613 24.897V.486zm40.242 0h7.248v35.03h-8.412l-15.515-25.043v25.042h-7.248V.485h8.315l15.612 24.897V.486z"/>
|
||||||
|
<path xmlns="http://www.w3.org/2000/svg" fill="#fff" d="M158.2 7.2a1.2 1.2 0 0 0 1.2-1.2V2.4h3.6a1.2 1.2 0 1 0 0-2.4h-4.8a1.2 1.2 0 0 0-1.2 1.2V6a1.2 1.2 0 0 0 1.2 1.2zM191.8 0H187a1.2 1.2 0 1 0 0 2.4h3.6V6a1.2 1.2 0 1 0 2.4 0V1.2a1.2 1.2 0 0 0-1.2-1.2zM163 33.6h-3.6V30a1.2 1.2 0 1 0-2.4 0v4.8a1.2 1.2 0 0 0 1.2 1.2h4.8a1.2 1.2 0 1 0 0-2.4zm28.8-4.8a1.2 1.2 0 0 0-1.2 1.2v3.6H187a1.2 1.2 0 1 0 0 2.4h4.8a1.2 1.2 0 0 0 1.2-1.2V30a1.2 1.2 0 0 0-1.2-1.2zM161.8 6a1.2 1.2 0 0 0 1.2 1.2h16.8a1.2 1.2 0 1 0 0-2.4H163a1.2 1.2 0 0 0-1.2 1.2zM187 16.8h-24a1.2 1.2 0 1 0 0 2.4h24a1.2 1.2 0 1 0 0-2.4zm-24 14.4h24a1.2 1.2 0 1 0 0-2.4h-24a1.2 1.2 0 1 0 0 2.4zm0-6h15.6a1.2 1.2 0 1 0 0-2.4H163a1.2 1.2 0 1 0 0 2.4zm24-14.4h-24a1.2 1.2 0 1 0 0 2.4h24a1.2 1.2 0 1 0 0-2.4z"/>
|
||||||
|
<path fill="#fff" d="M231.879 1.556a3.368 3.368 0 0 1 0 4.796l-11.666 11.665 11.666 11.666a3.236 3.236 0 0 1 0 4.75c-1.245 1.244-3.458 1.429-4.703.091L212.65 20l-11.665 11.666c-.231.23-.231.553 0 .784s.553.23.783 0l9.914-9.868c.553-.553 1.43-.553 1.983 0s.553 1.43 0 1.983l-9.96 9.96c-1.337 1.244-3.458 1.244-4.703-.093-1.337-1.245-1.337-3.412 0-4.749l11.666-11.666-11.666-11.665a3.368 3.368 0 0 1 0-4.796c1.245-1.29 3.504-1.29 4.75 0l9.774 9.775c.554.554.554 1.43 0 1.983s-1.429.553-1.982 0l-9.776-9.775c-.23-.23-.599-.23-.783 0a.584.584 0 0 0 0 .83l11.665 11.666 14.48-14.479c1.245-1.29 3.504-1.29 4.749 0zm-1.937 1.983c-.23-.23-.6-.23-.876.046l-14.432 14.432 14.432 14.433c.23.23.6.23.83 0 .185-.185.23-.554 0-.784l-12.68-12.634a1.392 1.392 0 0 1 0-1.983L229.85 4.415c.323-.323.323-.646.092-.876zM240.04.588c1.845 0 3.366 1.522 3.366 3.412v30.063c0 .738-.6 1.384-1.383 1.384s-1.43-.646-1.43-1.384V4c0-.323-.23-.6-.553-.6s-.6.277-.6.6v14.017c0 .784-.645 1.384-1.428 1.384-.738 0-1.384-.6-1.384-1.384V4A3.404 3.404 0 0 1 240.04.588zm24.853 3.458c3.735 0 7.24 1.43 9.868 4.058a14.027 14.027 0 0 1 4.057 9.913c0 .738-.599 1.384-1.383 1.384-.738 0-1.383-.646-1.383-1.384a11.12 11.12 0 0 0-3.274-7.93c-2.12-2.075-4.934-3.274-7.885-3.274-2.997 0-5.81 1.199-7.93 3.273a11.123 11.123 0 0 0-3.274 7.931c0 1.845-1.522 3.412-3.412 3.412s-3.412-1.567-3.412-3.412c0-4.841 1.89-9.36 5.256-12.726 7.055-7.055 18.444-7.055 25.499 0 3.412 3.366 5.256 7.885 5.256 12.726 0 4.796-1.844 9.314-5.256 12.727S269.689 36 264.893 36c-.783 0-1.429-.6-1.429-1.383s.646-1.384 1.43-1.384c4.057 0 7.884-1.613 10.743-4.472s4.473-6.686 4.473-10.744-1.614-7.884-4.473-10.79c-5.948-5.901-15.585-5.901-21.533 0a15.286 15.286 0 0 0-4.427 10.79c0 .415.23.692.646.692.369 0 .6-.23.6-.692 0-3.735 1.429-7.239 4.057-9.913 2.628-2.628 6.178-4.058 9.913-4.058zm25.683-2.351c3.735-2.168 8.577-.923 11.02 2.858L318.15 30.33c.968 1.613.415 3.78-1.199 4.703-1.43.784-3.458.645-4.611-1.245L295.879 8.242c-.323-.507-1.107-1.153-1.89-.692-.37.231-.646.646-.646 1.107v25.406c0 .738-.646 1.384-1.383 1.384-.784 0-1.43-.646-1.43-1.384V8.657a4.07 4.07 0 0 1 2.075-3.55c2.167-1.245 4.519-.093 5.626 1.613l16.46 25.545c.185.323.462.6.877.369s.322-.646.138-.876L299.245 6.075c-1.614-2.536-4.75-3.412-7.24-1.983-1.613.969-2.627 2.675-2.627 4.519v25.452c0 .738-.646 1.384-1.43 1.384-.738 0-1.383-.646-1.383-1.384V8.795c-.046-2.905 1.475-5.671 4.011-7.1zM315.245.634c1.89 0 3.412 1.522 3.412 3.366v19.781c0 .784-.645 1.383-1.383 1.383-.784 0-1.43-.6-1.43-1.383V4c0-.323-.276-.6-.6-.6s-.552.277-.552.6v13.233c0 .784-.646 1.43-1.43 1.43s-1.383-.646-1.383-1.43V4a3.385 3.385 0 0 1 3.366-3.366z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 6.3 KiB |
BIN
docs/images/sponsors/ML6.png
Normal file
BIN
docs/images/sponsors/ML6.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
@@ -198,7 +198,7 @@ Or with gunicorn:
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
$ gunicorn -k uvicorn.workers.UvicornWorker
|
$ gunicorn -k uvicorn.workers.UvicornWorker run:app
|
||||||
|
|
||||||
See the `uvicorn documentation`_ for more details.
|
See the `uvicorn documentation`_ for more details.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user