mirror of
https://github.com/LukeHagar/connexion.git
synced 2025-12-06 04:19:26 +00:00
Add ARCHITECTURE.rst and module docstrings (#1368)
* Add ARCHITECTURE.rst and module docstrings * fix flake8 Co-authored-by: Henning Jacobs <henning@zalando.de>
This commit is contained in:
74
ARCHITECTURE.rst
Normal file
74
ARCHITECTURE.rst
Normal file
@@ -0,0 +1,74 @@
|
||||
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 or
|
||||
AioHttp) 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
|
||||
@@ -568,6 +568,9 @@ Contributing to Connexion/TODOs
|
||||
We welcome your ideas, issues, and pull requests. Just follow the
|
||||
usual/standard GitHub practices.
|
||||
|
||||
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>`_.
|
||||
|
||||
Unless you explicitly state otherwise in advance, any non trivial
|
||||
contribution intentionally submitted for inclusion in this project by you
|
||||
to the steward of this repository (Zalando SE, Berlin) shall be under the
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
"""
|
||||
Connexion is a framework that automagically handles HTTP requests based on OpenAPI Specification
|
||||
(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.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
import werkzeug.exceptions as exceptions # NOQA
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module provides an entrypoint for Connexion's CLI.
|
||||
"""
|
||||
|
||||
from connexion.cli import main # pragma: no cover
|
||||
|
||||
main() # pragma: no cover
|
||||
|
||||
@@ -1 +1,16 @@
|
||||
"""
|
||||
This module defines Connexion APIs. 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.
|
||||
"""
|
||||
|
||||
|
||||
from .abstract import AbstractAPI # NOQA
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module defines an AbstractAPI, which defines a standardized interface for a Connexion API.
|
||||
"""
|
||||
|
||||
import abc
|
||||
import logging
|
||||
import pathlib
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
"""
|
||||
This module defines an AioHttp Connexion API which implements translations between AioHttp and
|
||||
Connexion requests / responses.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import re
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
"""
|
||||
This module defines a Flask Connexion API which implements translations between Flask and
|
||||
Connexion requests / responses.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import warnings
|
||||
from typing import Any
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module defines utility functions related to the Flask framework.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import random
|
||||
import re
|
||||
|
||||
@@ -1 +1,6 @@
|
||||
"""
|
||||
This module defines Connexion applications. A Connexion App wraps a specific framework application
|
||||
and exposes a standardized interface for users to create and configure their Connexion application.
|
||||
"""
|
||||
|
||||
from .abstract import AbstractApp # NOQA
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
"""
|
||||
This module defines an AbstractApp, which defines a standardized user interface for a Connexion
|
||||
application.
|
||||
"""
|
||||
|
||||
import abc
|
||||
import logging
|
||||
import pathlib
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module defines an AioHttpApp, a Connexion application to wrap an AioHttp application.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os.path
|
||||
import pkgutil
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module defines a FlaskApp, a Connexion application to wrap a Flask application.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import logging
|
||||
import pathlib
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
"""
|
||||
This module defines a command-line interface (CLI) that runs an OpenAPI specification to be a
|
||||
starting point for developing your API with Connexion.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import sys
|
||||
from os import path
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
"""
|
||||
This module defines decorators which Connexion uses to wrap user provided view functions.
|
||||
"""
|
||||
|
||||
0
connexion/decorators/coroutine_wrappers.py
Normal file
0
connexion/decorators/coroutine_wrappers.py
Normal file
@@ -1,3 +1,8 @@
|
||||
"""
|
||||
This module defines a BaseDecorator to wrap a user view function and a RequestResponseDecorator
|
||||
which manages the lifecycle of a request internally in Connexion.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import functools
|
||||
import logging
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
"""
|
||||
This module defines view function decorator to collect UWSGI metrics and expose them via an
|
||||
endpoint.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import os
|
||||
import time
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module defines a decorator to convert request parameters to arguments for the view function.
|
||||
"""
|
||||
|
||||
import builtins
|
||||
import functools
|
||||
import inspect
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# Decorators to change the return type of endpoints
|
||||
"""
|
||||
This module defines decorators to change the return type of a view function.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import logging
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# Decorators to change the return type of endpoints
|
||||
"""
|
||||
This module defines a view function decorator to validate its responses.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import functools
|
||||
import logging
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# Decorators to split query and path parameters
|
||||
"""
|
||||
This module defines view function decorators to split query and path parameters.
|
||||
"""
|
||||
|
||||
import abc
|
||||
import functools
|
||||
import json
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module defines view function decorators to validate request and response parameters and bodies.
|
||||
"""
|
||||
|
||||
import collections
|
||||
import copy
|
||||
import functools
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module defines Exception classes used by Connexion to generate a proper response.
|
||||
"""
|
||||
|
||||
import warnings
|
||||
|
||||
from jsonschema.exceptions import ValidationError
|
||||
@@ -14,7 +18,7 @@ class ProblemException(ConnexionException):
|
||||
def __init__(self, status=400, title=None, detail=None, type=None,
|
||||
instance=None, headers=None, ext=None):
|
||||
"""
|
||||
This exception is holds arguments that are going to be passed to the
|
||||
This exception holds arguments that are going to be passed to the
|
||||
`connexion.problem` function to generate a proper response.
|
||||
"""
|
||||
self.status = status
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module defines error handlers, operations that produce proper response problems.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from .exceptions import AuthenticationProblem, ResolverProblem
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module contains definitions of the HTTP protocol.
|
||||
"""
|
||||
|
||||
FORM_CONTENT_TYPES = [
|
||||
'application/x-www-form-urlencoded',
|
||||
'multipart/form-data'
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
Module containing all code related to json schema validation.
|
||||
"""
|
||||
|
||||
from collections.abc import Mapping
|
||||
from copy import deepcopy
|
||||
|
||||
|
||||
@@ -1,9 +1,22 @@
|
||||
"""
|
||||
This module centralizes all functionality related to json encoding and decoding in Connexion.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import uuid
|
||||
|
||||
|
||||
class JSONEncoder(json.JSONEncoder):
|
||||
"""The default Connexion JSON encoder. Handles extra types compared to the
|
||||
built-in :class:`json.JSONEncoder`.
|
||||
|
||||
- :class:`datetime.datetime` and :class:`datetime.date` are
|
||||
serialized to :rfc:`822` strings. This is the same as the HTTP
|
||||
date format.
|
||||
- :class:`uuid.UUID` is serialized to a string.
|
||||
"""
|
||||
|
||||
def default(self, o):
|
||||
if isinstance(o, datetime.datetime):
|
||||
if o.tzinfo:
|
||||
@@ -25,7 +38,7 @@ class JSONEncoder(json.JSONEncoder):
|
||||
|
||||
class Jsonifier:
|
||||
"""
|
||||
Used to serialized and deserialize to/from JSon
|
||||
Central point to serialize and deserialize to/from JSon in Connexion.
|
||||
"""
|
||||
def __init__(self, json_=json, **kwargs):
|
||||
"""
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
"""
|
||||
This module defines interfaces for requests and responses used in Connexion for authentication,
|
||||
validation, serialization, etc.
|
||||
"""
|
||||
|
||||
|
||||
class ConnexionRequest:
|
||||
"""Connexion interface for a request."""
|
||||
def __init__(self,
|
||||
url,
|
||||
method,
|
||||
@@ -27,6 +34,7 @@ class ConnexionRequest:
|
||||
|
||||
|
||||
class ConnexionResponse:
|
||||
"""Connexion interface for a response."""
|
||||
def __init__(self,
|
||||
status_code=200,
|
||||
mimetype=None,
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module contains a mock resolver that returns mock functions for operations it cannot resolve.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import logging
|
||||
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
"""
|
||||
This module defines Connexion Operation classes. A Connexion Operation implements an OpenAPI
|
||||
operation, 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.
|
||||
|
||||
"""
|
||||
|
||||
from .abstract import AbstractOperation # noqa
|
||||
from .openapi import OpenAPIOperation # noqa
|
||||
from .secure import SecureOperation # noqa
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
"""
|
||||
This module defines an AbstractOperation class which implements an abstract Operation interface
|
||||
and functionality shared between Swagger 2 and OpenAPI 3 specifications.
|
||||
"""
|
||||
|
||||
import abc
|
||||
import logging
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
# This is a dummy module for backwards compatibility with < v2.0
|
||||
"""
|
||||
This is a dummy module for backwards compatibility with < v2.0.
|
||||
"""
|
||||
from .secure import * # noqa
|
||||
from .swagger2 import * # noqa
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module defines an OpenAPIOperation class, a Connexion operation specific for OpenAPI 3 specs.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from copy import copy, deepcopy
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module defines a SecureOperation class, which implements the security handler for an operation.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import logging
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module defines a Swagger2Operation class, a Connexion operation specific for Swagger 2 specs.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from copy import deepcopy
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module defines a Connexion specific options class to pass to the Connexion App or API.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import pathlib
|
||||
from typing import Optional # NOQA
|
||||
@@ -19,6 +23,7 @@ logger = logging.getLogger("connexion.options")
|
||||
|
||||
|
||||
class ConnexionOptions:
|
||||
"""Class holding connexion specific options."""
|
||||
|
||||
def __init__(self, options=None, oas_version=(2,)):
|
||||
self._options = {}
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
"""
|
||||
This module contains a Python interface for Problem Details for HTTP APIs
|
||||
<https://tools.ietf.org/html/draft-ietf-appsawg-http-problem-00>, which is a standardized format
|
||||
to communicate distinct "problem types" to non-human consumers.
|
||||
"""
|
||||
|
||||
from .lifecycle import ConnexionResponse
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
"""
|
||||
This module contains resolvers, functions that resolves the user defined view functions
|
||||
from the operations defined in the OpenAPI spec.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import sys
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
"""isort:skip_file"""
|
||||
"""
|
||||
This module defines SecurityHandlerFactories which support the creation of security
|
||||
handlers for operations.
|
||||
|
||||
isort:skip_file
|
||||
"""
|
||||
|
||||
# abstract
|
||||
from .async_security_handler_factory import AbstractAsyncSecurityHandlerFactory # NOQA
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module defines an aiohttp-specific SecurityHandlerFactory.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
import aiohttp
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
"""
|
||||
This module defines an abstract asynchronous SecurityHandlerFactory which supports the creation of
|
||||
asynchronous security handlers for coroutine operations.
|
||||
"""
|
||||
|
||||
import abc
|
||||
import asyncio
|
||||
import functools
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module defines a Flask-specific SecurityHandlerFactory.
|
||||
"""
|
||||
|
||||
import requests
|
||||
|
||||
from .security_handler_factory import AbstractSecurityHandlerFactory
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
"""
|
||||
This module defines an abstract SecurityHandlerFactory which supports the creation of security
|
||||
handlers for operations.
|
||||
"""
|
||||
|
||||
import abc
|
||||
import base64
|
||||
import functools
|
||||
@@ -46,6 +51,12 @@ class AbstractSecurityHandlerFactory(abc.ABC):
|
||||
return default
|
||||
|
||||
def get_tokeninfo_func(self, security_definition: dict) -> t.Optional[t.Callable]:
|
||||
"""
|
||||
:type security_definition: dict
|
||||
|
||||
>>> get_tokeninfo_url({'x-tokenInfoFunc': 'foo.bar'})
|
||||
'<function foo.bar>'
|
||||
"""
|
||||
token_info_func = self._get_function(security_definition, "x-tokenInfoFunc", 'TOKENINFO_FUNC')
|
||||
if token_info_func:
|
||||
return token_info_func
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module defines Python interfaces for OpenAPI specifications.
|
||||
"""
|
||||
|
||||
import abc
|
||||
import copy
|
||||
import pathlib
|
||||
@@ -155,6 +159,8 @@ class Specification(Mapping):
|
||||
|
||||
|
||||
class Swagger2Specification(Specification):
|
||||
"""Python interface for a Swagger 2 specification."""
|
||||
|
||||
yaml_name = 'swagger.yaml'
|
||||
operation_cls = Swagger2Operation
|
||||
|
||||
@@ -210,6 +216,8 @@ class Swagger2Specification(Specification):
|
||||
|
||||
|
||||
class OpenAPISpecification(Specification):
|
||||
"""Python interface for an OpenAPI 3 specification."""
|
||||
|
||||
yaml_name = 'openapi.yaml'
|
||||
operation_cls = OpenAPIOperation
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
"""
|
||||
This module provides general utility functions used within Connexion.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import functools
|
||||
import importlib
|
||||
@@ -6,7 +10,7 @@ import yaml
|
||||
|
||||
|
||||
def boolean(s):
|
||||
'''
|
||||
"""
|
||||
Convert JSON/Swagger boolean value to Python, raise ValueError otherwise
|
||||
|
||||
>>> boolean('true')
|
||||
@@ -14,7 +18,7 @@ def boolean(s):
|
||||
|
||||
>>> boolean('false')
|
||||
False
|
||||
'''
|
||||
"""
|
||||
if isinstance(s, bool):
|
||||
return s
|
||||
elif not hasattr(s, 'lower'):
|
||||
|
||||
BIN
docs/images/architecture.png
Normal file
BIN
docs/images/architecture.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.9 MiB |
Reference in New Issue
Block a user