mirror of
https://github.com/correl/openapi-core.git
synced 2024-11-24 19:19:56 +00:00
commit
4e7d8edbb2
10 changed files with 561 additions and 299 deletions
6
Makefile
6
Makefile
|
@ -31,4 +31,10 @@ reports-cleanup:
|
||||||
|
|
||||||
test-cleanup: test-cache-cleanup reports-cleanup
|
test-cleanup: test-cache-cleanup reports-cleanup
|
||||||
|
|
||||||
|
docs-html:
|
||||||
|
sphinx-build -b html docs docs/_build
|
||||||
|
|
||||||
|
docs-cleanup:
|
||||||
|
@rm -rf docs/_build
|
||||||
|
|
||||||
cleanup: dist-cleanup test-cleanup
|
cleanup: dist-cleanup test-cleanup
|
||||||
|
|
319
README.rst
319
README.rst
|
@ -19,7 +19,24 @@ About
|
||||||
#####
|
#####
|
||||||
|
|
||||||
Openapi-core is a Python library that adds client-side and server-side support
|
Openapi-core is a Python library that adds client-side and server-side support
|
||||||
for the `OpenAPI Specification v3.0.0 <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md>`__.
|
for the `OpenAPI Specification v3 <https://github.com/OAI/OpenAPI-Specification>`__.
|
||||||
|
|
||||||
|
Key features
|
||||||
|
************
|
||||||
|
|
||||||
|
* **Validation** of requests and responses
|
||||||
|
* Schema **casting** and **unmarshalling**
|
||||||
|
* Media type and parameters **deserialization**
|
||||||
|
* **Security** providers (API keys, Cookie, Basic and Bearer HTTP authentications)
|
||||||
|
* Custom **deserializers** and **formats**
|
||||||
|
* **Integration** with libraries and frameworks
|
||||||
|
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
#############
|
||||||
|
|
||||||
|
Check documentation to see more details about the features. All documentation is in the "docs" directory and online at `openapi-core.readthedocs.io <https://openapi-core.readthedocs.io>`__
|
||||||
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
############
|
############
|
||||||
|
@ -81,7 +98,7 @@ and unmarshal request data from validation result
|
||||||
# get security data
|
# get security data
|
||||||
validated_security = result.security
|
validated_security = result.security
|
||||||
|
|
||||||
Request object should be instance of OpenAPIRequest class (See `Integrations`_).
|
Request object should be instance of OpenAPIRequest class (See `Integrations <https://openapi-core.readthedocs.io/en/latest/integrations.html>`__).
|
||||||
|
|
||||||
Response
|
Response
|
||||||
********
|
********
|
||||||
|
@ -111,303 +128,7 @@ and unmarshal response data from validation result
|
||||||
# get data
|
# get data
|
||||||
validated_data = result.data
|
validated_data = result.data
|
||||||
|
|
||||||
Response object should be instance of OpenAPIResponse class (See `Integrations`_).
|
Response object should be instance of OpenAPIResponse class (See `Integrations <https://openapi-core.readthedocs.io/en/latest/integrations.html>`__).
|
||||||
|
|
||||||
Security
|
|
||||||
********
|
|
||||||
|
|
||||||
openapi-core supports security for authentication and authorization process. Security data for security schemas are accessible from `security` attribute of `RequestValidationResult` object.
|
|
||||||
|
|
||||||
For given security specification:
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
|
|
||||||
security:
|
|
||||||
- BasicAuth: []
|
|
||||||
- ApiKeyAuth: []
|
|
||||||
components:
|
|
||||||
securitySchemes:
|
|
||||||
BasicAuth:
|
|
||||||
type: http
|
|
||||||
scheme: basic
|
|
||||||
ApiKeyAuth:
|
|
||||||
type: apiKey
|
|
||||||
in: header
|
|
||||||
name: X-API-Key
|
|
||||||
|
|
||||||
you can access your security data the following:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
result = validator.validate(request)
|
|
||||||
|
|
||||||
# get basic auth decoded credentials
|
|
||||||
result.security['BasicAuth']
|
|
||||||
|
|
||||||
# get api key
|
|
||||||
result.security['ApiKeyAuth']
|
|
||||||
|
|
||||||
Supported security types:
|
|
||||||
|
|
||||||
* http – for Basic and Bearer HTTP authentications schemes
|
|
||||||
* apiKey – for API keys and cookie authentication
|
|
||||||
|
|
||||||
|
|
||||||
Customizations
|
|
||||||
##############
|
|
||||||
|
|
||||||
Spec validation
|
|
||||||
***************
|
|
||||||
|
|
||||||
By default, spec dict is validated on spec creation time. Disabling the validation can improve the performance.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from openapi_core import create_spec
|
|
||||||
|
|
||||||
spec = create_spec(spec_dict, validate_spec=False)
|
|
||||||
|
|
||||||
Deserializers
|
|
||||||
*************
|
|
||||||
|
|
||||||
Pass custom defined media type deserializers dictionary with supported mimetypes as a key to `RequestValidator` or `ResponseValidator` constructor:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
def protobuf_deserializer(message):
|
|
||||||
feature = route_guide_pb2.Feature()
|
|
||||||
feature.ParseFromString(message)
|
|
||||||
return feature
|
|
||||||
|
|
||||||
custom_media_type_deserializers = {
|
|
||||||
'application/protobuf': protobuf_deserializer,
|
|
||||||
}
|
|
||||||
|
|
||||||
validator = ResponseValidator(
|
|
||||||
spec, custom_media_type_deserializers=custom_media_type_deserializers)
|
|
||||||
|
|
||||||
result = validator.validate(request, response)
|
|
||||||
|
|
||||||
Formats
|
|
||||||
*******
|
|
||||||
|
|
||||||
OpenAPI defines a ``format`` keyword that hints at how a value should be interpreted, e.g. a ``string`` with the type ``date`` should conform to the RFC 3339 date format.
|
|
||||||
|
|
||||||
Openapi-core comes with a set of built-in formatters, but it's also possible to add support for custom formatters for `RequestValidator` and `ResponseValidator`.
|
|
||||||
|
|
||||||
Here's how you could add support for a ``usdate`` format that handles dates of the form MM/DD/YYYY:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
import re
|
|
||||||
|
|
||||||
class USDateFormatter:
|
|
||||||
def validate(self, value) -> bool:
|
|
||||||
return bool(re.match(r"^\d{1,2}/\d{1,2}/\d{4}$", value))
|
|
||||||
|
|
||||||
def unmarshal(self, value):
|
|
||||||
return datetime.strptime(value, "%m/%d/%y").date
|
|
||||||
|
|
||||||
|
|
||||||
custom_formatters = {
|
|
||||||
'usdate': USDateFormatter(),
|
|
||||||
}
|
|
||||||
|
|
||||||
validator = ResponseValidator(spec, custom_formatters=custom_formatters)
|
|
||||||
|
|
||||||
result = validator.validate(request, response)
|
|
||||||
|
|
||||||
Integrations
|
|
||||||
############
|
|
||||||
|
|
||||||
Django
|
|
||||||
******
|
|
||||||
|
|
||||||
For Django 2.2 you can use DjangoOpenAPIRequest a Django request factory:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from openapi_core.validation.request.validators import RequestValidator
|
|
||||||
from openapi_core.contrib.django import DjangoOpenAPIRequest
|
|
||||||
|
|
||||||
openapi_request = DjangoOpenAPIRequest(django_request)
|
|
||||||
validator = RequestValidator(spec)
|
|
||||||
result = validator.validate(openapi_request)
|
|
||||||
|
|
||||||
You can use DjangoOpenAPIResponse as a Django response factory:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from openapi_core.validation.response.validators import ResponseValidator
|
|
||||||
from openapi_core.contrib.django import DjangoOpenAPIResponse
|
|
||||||
|
|
||||||
openapi_response = DjangoOpenAPIResponse(django_response)
|
|
||||||
validator = ResponseValidator(spec)
|
|
||||||
result = validator.validate(openapi_request, openapi_response)
|
|
||||||
|
|
||||||
Falcon
|
|
||||||
******
|
|
||||||
|
|
||||||
This section describes integration with `Falcon <https://falconframework.org>`__ web framework.
|
|
||||||
|
|
||||||
Middleware
|
|
||||||
==========
|
|
||||||
|
|
||||||
Falcon API can be integrated by `FalconOpenAPIMiddleware` middleware.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from openapi_core.contrib.falcon.middlewares import FalconOpenAPIMiddleware
|
|
||||||
|
|
||||||
openapi_middleware = FalconOpenAPIMiddleware.from_spec(spec)
|
|
||||||
api = falcon.API(middleware=[openapi_middleware])
|
|
||||||
|
|
||||||
Low level
|
|
||||||
=========
|
|
||||||
|
|
||||||
For Falcon you can use FalconOpenAPIRequest a Falcon request factory:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from openapi_core.validation.request.validators import RequestValidator
|
|
||||||
from openapi_core.contrib.falcon import FalconOpenAPIRequestFactory
|
|
||||||
|
|
||||||
openapi_request = FalconOpenAPIRequestFactory.create(falcon_request)
|
|
||||||
validator = RequestValidator(spec)
|
|
||||||
result = validator.validate(openapi_request)
|
|
||||||
|
|
||||||
You can use FalconOpenAPIResponse as a Falcon response factory:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from openapi_core.validation.response.validators import ResponseValidator
|
|
||||||
from openapi_core.contrib.falcon import FalconOpenAPIResponseFactory
|
|
||||||
|
|
||||||
openapi_response = FalconOpenAPIResponseFactory.create(falcon_response)
|
|
||||||
validator = ResponseValidator(spec)
|
|
||||||
result = validator.validate(openapi_request, openapi_response)
|
|
||||||
|
|
||||||
Flask
|
|
||||||
*****
|
|
||||||
|
|
||||||
Decorator
|
|
||||||
=========
|
|
||||||
|
|
||||||
Flask views can be integrated by `FlaskOpenAPIViewDecorator` decorator.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from openapi_core.contrib.flask.decorators import FlaskOpenAPIViewDecorator
|
|
||||||
|
|
||||||
openapi = FlaskOpenAPIViewDecorator.from_spec(spec)
|
|
||||||
|
|
||||||
@app.route('/home')
|
|
||||||
@openapi
|
|
||||||
def home():
|
|
||||||
pass
|
|
||||||
|
|
||||||
If you want to decorate class based view you can use the decorators attribute:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
class MyView(View):
|
|
||||||
decorators = [openapi]
|
|
||||||
|
|
||||||
View
|
|
||||||
====
|
|
||||||
|
|
||||||
As an alternative to the decorator-based integration, Flask method based views can be integrated by inheritance from `FlaskOpenAPIView` class.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from openapi_core.contrib.flask.views import FlaskOpenAPIView
|
|
||||||
|
|
||||||
class MyView(FlaskOpenAPIView):
|
|
||||||
pass
|
|
||||||
|
|
||||||
app.add_url_rule('/home', view_func=MyView.as_view('home', spec))
|
|
||||||
|
|
||||||
Request parameters
|
|
||||||
==================
|
|
||||||
|
|
||||||
In Flask, all unmarshalled request data are provided as Flask request object's openapi.parameters attribute
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from flask.globals import request
|
|
||||||
|
|
||||||
@app.route('/browse/<id>/')
|
|
||||||
@openapi
|
|
||||||
def home():
|
|
||||||
browse_id = request.openapi.parameters.path['id']
|
|
||||||
page = request.openapi.parameters.query.get('page', 1)
|
|
||||||
|
|
||||||
Low level
|
|
||||||
=========
|
|
||||||
|
|
||||||
You can use FlaskOpenAPIRequest a Flask/Werkzeug request factory:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from openapi_core.validation.request.validators import RequestValidator
|
|
||||||
from openapi_core.contrib.flask import FlaskOpenAPIRequest
|
|
||||||
|
|
||||||
openapi_request = FlaskOpenAPIRequest(flask_request)
|
|
||||||
validator = RequestValidator(spec)
|
|
||||||
result = validator.validate(openapi_request)
|
|
||||||
|
|
||||||
You can use FlaskOpenAPIResponse as a Flask/Werkzeug response factory:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from openapi_core.validation.response.validators import ResponseValidator
|
|
||||||
from openapi_core.contrib.flask import FlaskOpenAPIResponse
|
|
||||||
|
|
||||||
openapi_response = FlaskOpenAPIResponse(flask_response)
|
|
||||||
validator = ResponseValidator(spec)
|
|
||||||
result = validator.validate(openapi_request, openapi_response)
|
|
||||||
|
|
||||||
Pyramid
|
|
||||||
*******
|
|
||||||
|
|
||||||
See `pyramid_openapi3 <https://github.com/niteoweb/pyramid_openapi3>`_ project.
|
|
||||||
|
|
||||||
Bottle
|
|
||||||
*******
|
|
||||||
|
|
||||||
See `bottle-openapi-3 <https://github.com/cope-systems/bottle-openapi-3>`_ project.
|
|
||||||
|
|
||||||
|
|
||||||
Requests
|
|
||||||
********
|
|
||||||
|
|
||||||
This section describes integration with `Requests <https://requests.readthedocs.io>`__ library.
|
|
||||||
|
|
||||||
Low level
|
|
||||||
=========
|
|
||||||
|
|
||||||
For Requests you can use RequestsOpenAPIRequest a Requests request factory:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from openapi_core.validation.request.validators import RequestValidator
|
|
||||||
from openapi_core.contrib.requests import RequestsOpenAPIRequest
|
|
||||||
|
|
||||||
openapi_request = RequestsOpenAPIRequest(requests_request)
|
|
||||||
validator = RequestValidator(spec)
|
|
||||||
result = validator.validate(openapi_request)
|
|
||||||
|
|
||||||
You can use RequestsOpenAPIResponse as a Requests response factory:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from openapi_core.validation.response.validators import ResponseValidator
|
|
||||||
from openapi_core.contrib.requests import RequestsOpenAPIResponse
|
|
||||||
|
|
||||||
openapi_response = RequestsOpenAPIResponse(requests_response)
|
|
||||||
validator = ResponseValidator(spec)
|
|
||||||
result = validator.validate(openapi_request, openapi_response)
|
|
||||||
|
|
||||||
Related projects
|
Related projects
|
||||||
################
|
################
|
||||||
|
|
61
docs/conf.py
Normal file
61
docs/conf.py
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
# Configuration file for the Sphinx documentation builder.
|
||||||
|
#
|
||||||
|
# This file only contains a selection of the most common options. For a full
|
||||||
|
# list see the documentation:
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||||
|
|
||||||
|
# -- Path setup --------------------------------------------------------------
|
||||||
|
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
#
|
||||||
|
# import os
|
||||||
|
# import sys
|
||||||
|
# sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
|
import openapi_core
|
||||||
|
|
||||||
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
|
project = 'openapi-core'
|
||||||
|
copyright = '2021, Artur Maciag'
|
||||||
|
author = 'Artur Maciag'
|
||||||
|
|
||||||
|
# The full version, including alpha/beta/rc tags
|
||||||
|
release = openapi_core.__version__
|
||||||
|
|
||||||
|
|
||||||
|
# -- General configuration ---------------------------------------------------
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
|
# ones.
|
||||||
|
extensions = [
|
||||||
|
"sphinx.ext.autodoc",
|
||||||
|
"sphinx.ext.doctest",
|
||||||
|
"sphinx.ext.intersphinx",
|
||||||
|
"sphinx.ext.coverage",
|
||||||
|
"sphinx.ext.viewcode",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
# This pattern also affects html_static_path and html_extra_path.
|
||||||
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output -------------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
#
|
||||||
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['_static']
|
65
docs/customizations.rst
Normal file
65
docs/customizations.rst
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
Customizations
|
||||||
|
==============
|
||||||
|
|
||||||
|
Spec validation
|
||||||
|
---------------
|
||||||
|
|
||||||
|
By default, spec dict is validated on spec creation time. Disabling the validation can improve the performance.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from openapi_core import create_spec
|
||||||
|
|
||||||
|
spec = create_spec(spec_dict, validate_spec=False)
|
||||||
|
|
||||||
|
Deserializers
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Pass custom defined media type deserializers dictionary with supported mimetypes as a key to `RequestValidator` or `ResponseValidator` constructor:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
def protobuf_deserializer(message):
|
||||||
|
feature = route_guide_pb2.Feature()
|
||||||
|
feature.ParseFromString(message)
|
||||||
|
return feature
|
||||||
|
|
||||||
|
custom_media_type_deserializers = {
|
||||||
|
'application/protobuf': protobuf_deserializer,
|
||||||
|
}
|
||||||
|
|
||||||
|
validator = ResponseValidator(
|
||||||
|
spec, custom_media_type_deserializers=custom_media_type_deserializers)
|
||||||
|
|
||||||
|
result = validator.validate(request, response)
|
||||||
|
|
||||||
|
Formats
|
||||||
|
-------
|
||||||
|
|
||||||
|
OpenAPI defines a ``format`` keyword that hints at how a value should be interpreted, e.g. a ``string`` with the type ``date`` should conform to the RFC 3339 date format.
|
||||||
|
|
||||||
|
Openapi-core comes with a set of built-in formatters, but it's also possible to add support for custom formatters for `RequestValidator` and `ResponseValidator`.
|
||||||
|
|
||||||
|
Here's how you could add support for a ``usdate`` format that handles dates of the form MM/DD/YYYY:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
import re
|
||||||
|
|
||||||
|
class USDateFormatter:
|
||||||
|
def validate(self, value) -> bool:
|
||||||
|
return bool(re.match(r"^\d{1,2}/\d{1,2}/\d{4}$", value))
|
||||||
|
|
||||||
|
def unmarshal(self, value):
|
||||||
|
return datetime.strptime(value, "%m/%d/%y").date
|
||||||
|
|
||||||
|
|
||||||
|
custom_formatters = {
|
||||||
|
'usdate': USDateFormatter(),
|
||||||
|
}
|
||||||
|
|
||||||
|
validator = ResponseValidator(spec, custom_formatters=custom_formatters)
|
||||||
|
|
||||||
|
result = validator.validate(request, response)
|
||||||
|
|
43
docs/index.rst
Normal file
43
docs/index.rst
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
.. openapi-core documentation master file, created by
|
||||||
|
sphinx-quickstart on Tue Feb 2 17:41:34 2021.
|
||||||
|
You can adapt this file completely to your liking, but it should at least
|
||||||
|
contain the root `toctree` directive.
|
||||||
|
|
||||||
|
Welcome to openapi-core's documentation!
|
||||||
|
========================================
|
||||||
|
|
||||||
|
Openapi-core is a Python library that adds client-side and server-side support
|
||||||
|
for the `OpenAPI Specification v3 <https://github.com/OAI/OpenAPI-Specification>`__.
|
||||||
|
|
||||||
|
Key features
|
||||||
|
------------
|
||||||
|
|
||||||
|
* **Validation** of requests and responses
|
||||||
|
* Schema **casting** and **unmarshalling**
|
||||||
|
* Media type and parameters **deserialization**
|
||||||
|
* **Security** providers (API keys, Cookie, Basic and Bearer HTTP authentications)
|
||||||
|
* Custom **deserializers** and **formats**
|
||||||
|
* **Integration** with libraries and frameworks
|
||||||
|
|
||||||
|
|
||||||
|
Table of contents
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. Navigation/TOC
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
installation
|
||||||
|
usage
|
||||||
|
customizations
|
||||||
|
integrations
|
||||||
|
|
||||||
|
|
||||||
|
Related projects
|
||||||
|
================
|
||||||
|
|
||||||
|
* `openapi-spec-validator <https://github.com/p1c2u/openapi-spec-validator>`__
|
||||||
|
Python library that validates OpenAPI Specs against the OpenAPI 2.0 (aka Swagger) and OpenAPI 3.0.0 specification. The validator aims to check for full compliance with the Specification.
|
||||||
|
* `openapi-schema-validator <https://github.com/p1c2u/openapi-schema-validator>`__
|
||||||
|
Python library that validates schema against the OpenAPI Schema Specification v3.0 which is an extended subset of the JSON Schema Specification Wright Draft 00.
|
15
docs/installation.rst
Normal file
15
docs/installation.rst
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
Recommended way (via pip):
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ pip install openapi-core
|
||||||
|
|
||||||
|
Alternatively you can download the code and install from the repository:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ pip install -e git+https://github.com/p1c2u/openapi-core.git#egg=openapi_core
|
||||||
|
|
198
docs/integrations.rst
Normal file
198
docs/integrations.rst
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
Integrations
|
||||||
|
============
|
||||||
|
|
||||||
|
Bottle
|
||||||
|
------
|
||||||
|
|
||||||
|
See `bottle-openapi-3 <https://github.com/cope-systems/bottle-openapi-3>`_ project.
|
||||||
|
|
||||||
|
|
||||||
|
Django
|
||||||
|
------
|
||||||
|
|
||||||
|
This section describes integration with `Django <https://www.djangoproject.com>`__ web framework.
|
||||||
|
|
||||||
|
For Django 2.2 you can use DjangoOpenAPIRequest a Django request factory:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from openapi_core.validation.request.validators import RequestValidator
|
||||||
|
from openapi_core.contrib.django import DjangoOpenAPIRequest
|
||||||
|
|
||||||
|
openapi_request = DjangoOpenAPIRequest(django_request)
|
||||||
|
validator = RequestValidator(spec)
|
||||||
|
result = validator.validate(openapi_request)
|
||||||
|
|
||||||
|
You can use DjangoOpenAPIResponse as a Django response factory:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from openapi_core.validation.response.validators import ResponseValidator
|
||||||
|
from openapi_core.contrib.django import DjangoOpenAPIResponse
|
||||||
|
|
||||||
|
openapi_response = DjangoOpenAPIResponse(django_response)
|
||||||
|
validator = ResponseValidator(spec)
|
||||||
|
result = validator.validate(openapi_request, openapi_response)
|
||||||
|
|
||||||
|
|
||||||
|
Falcon
|
||||||
|
------
|
||||||
|
|
||||||
|
This section describes integration with `Falcon <https://falconframework.org>`__ web framework.
|
||||||
|
|
||||||
|
Middleware
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
Falcon API can be integrated by `FalconOpenAPIMiddleware` middleware.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from openapi_core.contrib.falcon.middlewares import FalconOpenAPIMiddleware
|
||||||
|
|
||||||
|
openapi_middleware = FalconOpenAPIMiddleware.from_spec(spec)
|
||||||
|
api = falcon.API(middleware=[openapi_middleware])
|
||||||
|
|
||||||
|
Low level
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
For Falcon you can use FalconOpenAPIRequest a Falcon request factory:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from openapi_core.validation.request.validators import RequestValidator
|
||||||
|
from openapi_core.contrib.falcon import FalconOpenAPIRequestFactory
|
||||||
|
|
||||||
|
openapi_request = FalconOpenAPIRequestFactory.create(falcon_request)
|
||||||
|
validator = RequestValidator(spec)
|
||||||
|
result = validator.validate(openapi_request)
|
||||||
|
|
||||||
|
You can use FalconOpenAPIResponse as a Falcon response factory:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from openapi_core.validation.response.validators import ResponseValidator
|
||||||
|
from openapi_core.contrib.falcon import FalconOpenAPIResponseFactory
|
||||||
|
|
||||||
|
openapi_response = FalconOpenAPIResponseFactory.create(falcon_response)
|
||||||
|
validator = ResponseValidator(spec)
|
||||||
|
result = validator.validate(openapi_request, openapi_response)
|
||||||
|
|
||||||
|
|
||||||
|
Flask
|
||||||
|
-----
|
||||||
|
|
||||||
|
This section describes integration with `Flask <https://flask.palletsprojects.com>`__ web framework.
|
||||||
|
|
||||||
|
Decorator
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
Flask views can be integrated by `FlaskOpenAPIViewDecorator` decorator.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from openapi_core.contrib.flask.decorators import FlaskOpenAPIViewDecorator
|
||||||
|
|
||||||
|
openapi = FlaskOpenAPIViewDecorator.from_spec(spec)
|
||||||
|
|
||||||
|
@app.route('/home')
|
||||||
|
@openapi
|
||||||
|
def home():
|
||||||
|
pass
|
||||||
|
|
||||||
|
If you want to decorate class based view you can use the decorators attribute:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
class MyView(View):
|
||||||
|
decorators = [openapi]
|
||||||
|
|
||||||
|
View
|
||||||
|
~~~~
|
||||||
|
|
||||||
|
As an alternative to the decorator-based integration, Flask method based views can be integrated by inheritance from `FlaskOpenAPIView` class.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from openapi_core.contrib.flask.views import FlaskOpenAPIView
|
||||||
|
|
||||||
|
class MyView(FlaskOpenAPIView):
|
||||||
|
pass
|
||||||
|
|
||||||
|
app.add_url_rule('/home', view_func=MyView.as_view('home', spec))
|
||||||
|
|
||||||
|
Request parameters
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
In Flask, all unmarshalled request data are provided as Flask request object's openapi.parameters attribute
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from flask.globals import request
|
||||||
|
|
||||||
|
@app.route('/browse/<id>/')
|
||||||
|
@openapi
|
||||||
|
def home():
|
||||||
|
browse_id = request.openapi.parameters.path['id']
|
||||||
|
page = request.openapi.parameters.query.get('page', 1)
|
||||||
|
|
||||||
|
Low level
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
You can use FlaskOpenAPIRequest a Flask/Werkzeug request factory:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from openapi_core.validation.request.validators import RequestValidator
|
||||||
|
from openapi_core.contrib.flask import FlaskOpenAPIRequest
|
||||||
|
|
||||||
|
openapi_request = FlaskOpenAPIRequest(flask_request)
|
||||||
|
validator = RequestValidator(spec)
|
||||||
|
result = validator.validate(openapi_request)
|
||||||
|
|
||||||
|
You can use FlaskOpenAPIResponse as a Flask/Werkzeug response factory:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from openapi_core.validation.response.validators import ResponseValidator
|
||||||
|
from openapi_core.contrib.flask import FlaskOpenAPIResponse
|
||||||
|
|
||||||
|
openapi_response = FlaskOpenAPIResponse(flask_response)
|
||||||
|
validator = ResponseValidator(spec)
|
||||||
|
result = validator.validate(openapi_request, openapi_response)
|
||||||
|
|
||||||
|
|
||||||
|
Pyramid
|
||||||
|
-------
|
||||||
|
|
||||||
|
See `pyramid_openapi3 <https://github.com/niteoweb/pyramid_openapi3>`_ project.
|
||||||
|
|
||||||
|
|
||||||
|
Requests
|
||||||
|
--------
|
||||||
|
|
||||||
|
This section describes integration with `Requests <https://requests.readthedocs.io>`__ library.
|
||||||
|
|
||||||
|
Low level
|
||||||
|
~~~~~~~~~
|
||||||
|
|
||||||
|
For Requests you can use RequestsOpenAPIRequest a Requests request factory:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from openapi_core.validation.request.validators import RequestValidator
|
||||||
|
from openapi_core.contrib.requests import RequestsOpenAPIRequest
|
||||||
|
|
||||||
|
openapi_request = RequestsOpenAPIRequest(requests_request)
|
||||||
|
validator = RequestValidator(spec)
|
||||||
|
result = validator.validate(openapi_request)
|
||||||
|
|
||||||
|
You can use RequestsOpenAPIResponse as a Requests response factory:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from openapi_core.validation.response.validators import ResponseValidator
|
||||||
|
from openapi_core.contrib.requests import RequestsOpenAPIResponse
|
||||||
|
|
||||||
|
openapi_response = RequestsOpenAPIResponse(requests_response)
|
||||||
|
validator = ResponseValidator(spec)
|
||||||
|
result = validator.validate(openapi_request, openapi_response)
|
35
docs/make.bat
Normal file
35
docs/make.bat
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
@ECHO OFF
|
||||||
|
|
||||||
|
pushd %~dp0
|
||||||
|
|
||||||
|
REM Command file for Sphinx documentation
|
||||||
|
|
||||||
|
if "%SPHINXBUILD%" == "" (
|
||||||
|
set SPHINXBUILD=sphinx-build
|
||||||
|
)
|
||||||
|
set SOURCEDIR=.
|
||||||
|
set BUILDDIR=_build
|
||||||
|
|
||||||
|
if "%1" == "" goto help
|
||||||
|
|
||||||
|
%SPHINXBUILD% >NUL 2>NUL
|
||||||
|
if errorlevel 9009 (
|
||||||
|
echo.
|
||||||
|
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||||
|
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||||
|
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||||
|
echo.may add the Sphinx directory to PATH.
|
||||||
|
echo.
|
||||||
|
echo.If you don't have Sphinx installed, grab it from
|
||||||
|
echo.http://sphinx-doc.org/
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:help
|
||||||
|
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||||
|
|
||||||
|
:end
|
||||||
|
popd
|
2
docs/requirements.txt
Normal file
2
docs/requirements.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
sphinx
|
||||||
|
sphinx_rtd_theme
|
116
docs/usage.rst
Normal file
116
docs/usage.rst
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
Usage
|
||||||
|
=====
|
||||||
|
|
||||||
|
Firstly create your specification:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from openapi_core import create_spec
|
||||||
|
|
||||||
|
spec = create_spec(spec_dict)
|
||||||
|
|
||||||
|
|
||||||
|
Request
|
||||||
|
-------
|
||||||
|
|
||||||
|
Now you can use it to validate requests
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from openapi_core.validation.request.validators import RequestValidator
|
||||||
|
|
||||||
|
validator = RequestValidator(spec)
|
||||||
|
result = validator.validate(request)
|
||||||
|
|
||||||
|
# raise errors if request invalid
|
||||||
|
result.raise_for_errors()
|
||||||
|
|
||||||
|
# get list of errors
|
||||||
|
errors = result.errors
|
||||||
|
|
||||||
|
and unmarshal request data from validation result
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# get parameters object with path, query, cookies and headers parameters
|
||||||
|
validated_params = result.parameters
|
||||||
|
# or specific parameters
|
||||||
|
validated_path_params = result.parameters.path
|
||||||
|
|
||||||
|
# get body
|
||||||
|
validated_body = result.body
|
||||||
|
|
||||||
|
# get security data
|
||||||
|
validated_security = result.security
|
||||||
|
|
||||||
|
Request object should be instance of OpenAPIRequest class (See :doc:`integrations`).
|
||||||
|
|
||||||
|
Response
|
||||||
|
--------
|
||||||
|
|
||||||
|
You can also validate responses
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
from openapi_core.validation.response.validators import ResponseValidator
|
||||||
|
|
||||||
|
validator = ResponseValidator(spec)
|
||||||
|
result = validator.validate(request, response)
|
||||||
|
|
||||||
|
# raise errors if response invalid
|
||||||
|
result.raise_for_errors()
|
||||||
|
|
||||||
|
# get list of errors
|
||||||
|
errors = result.errors
|
||||||
|
|
||||||
|
and unmarshal response data from validation result
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# get headers
|
||||||
|
validated_headers = result.headers
|
||||||
|
|
||||||
|
# get data
|
||||||
|
validated_data = result.data
|
||||||
|
|
||||||
|
Response object should be instance of OpenAPIResponse class (See :doc:`integrations`).
|
||||||
|
|
||||||
|
Security
|
||||||
|
--------
|
||||||
|
|
||||||
|
openapi-core supports security for authentication and authorization process. Security data for security schemas are accessible from `security` attribute of `RequestValidationResult` object.
|
||||||
|
|
||||||
|
For given security specification:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
security:
|
||||||
|
- BasicAuth: []
|
||||||
|
- ApiKeyAuth: []
|
||||||
|
components:
|
||||||
|
securitySchemes:
|
||||||
|
BasicAuth:
|
||||||
|
type: http
|
||||||
|
scheme: basic
|
||||||
|
ApiKeyAuth:
|
||||||
|
type: apiKey
|
||||||
|
in: header
|
||||||
|
name: X-API-Key
|
||||||
|
|
||||||
|
you can access your security data the following:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
result = validator.validate(request)
|
||||||
|
|
||||||
|
# get basic auth decoded credentials
|
||||||
|
result.security['BasicAuth']
|
||||||
|
|
||||||
|
# get api key
|
||||||
|
result.security['ApiKeyAuth']
|
||||||
|
|
||||||
|
Supported security types:
|
||||||
|
|
||||||
|
* http – for Basic and Bearer HTTP authentications schemes
|
||||||
|
* apiKey – for API keys and cookie authentication
|
||||||
|
|
Loading…
Reference in a new issue