mirror of
https://github.com/LukeHagar/connexion.git
synced 2025-12-06 04:19:26 +00:00
Add swagger-ui docs and clean up swagger-ui options (#1739)
Contributes to #1531
This commit is contained in:
@@ -12,6 +12,7 @@ from starlette.types import ASGIApp, Receive, Scope, Send
|
||||
from connexion.jsonifier import Jsonifier
|
||||
from connexion.middleware import ConnexionMiddleware, MiddlewarePosition, SpecMiddleware
|
||||
from connexion.middleware.lifespan import Lifespan
|
||||
from connexion.options import SwaggerUIOptions
|
||||
from connexion.resolver import Resolver
|
||||
from connexion.uri_parsing import AbstractURIParser
|
||||
|
||||
@@ -43,7 +44,7 @@ class AbstractApp:
|
||||
resolver: t.Optional[t.Union[Resolver, t.Callable]] = None,
|
||||
resolver_error: t.Optional[int] = None,
|
||||
strict_validation: t.Optional[bool] = None,
|
||||
swagger_ui_options: t.Optional[dict] = None,
|
||||
swagger_ui_options: t.Optional[SwaggerUIOptions] = None,
|
||||
uri_parser_class: t.Optional[AbstractURIParser] = None,
|
||||
validate_responses: t.Optional[bool] = None,
|
||||
validator_map: t.Optional[dict] = None,
|
||||
@@ -72,8 +73,8 @@ class AbstractApp:
|
||||
start.
|
||||
:param strict_validation: When True, extra form or query parameters not defined in the
|
||||
specification result in a validation error. Defaults to False.
|
||||
:param swagger_ui_options: A dict with configuration options for the swagger ui. See
|
||||
:class:`options.ConnexionOptions`.
|
||||
:param swagger_ui_options: Instance of :class:`options.ConnexionOptions` with
|
||||
configuration options for the swagger ui.
|
||||
:param uri_parser_class: Class to use for uri parsing. See :mod:`uri_parsing`.
|
||||
:param validate_responses: Whether to validate responses against the specification. This has
|
||||
an impact on performance. Defaults to False.
|
||||
@@ -128,7 +129,7 @@ class AbstractApp:
|
||||
resolver: t.Optional[t.Union[Resolver, t.Callable]] = None,
|
||||
resolver_error: t.Optional[int] = None,
|
||||
strict_validation: t.Optional[bool] = None,
|
||||
swagger_ui_options: t.Optional[dict] = None,
|
||||
swagger_ui_options: t.Optional[SwaggerUIOptions] = None,
|
||||
uri_parser_class: t.Optional[AbstractURIParser] = None,
|
||||
validate_responses: t.Optional[bool] = None,
|
||||
validator_map: t.Optional[dict] = None,
|
||||
|
||||
@@ -17,6 +17,7 @@ from connexion.jsonifier import Jsonifier
|
||||
from connexion.middleware.abstract import RoutedAPI, RoutedMiddleware
|
||||
from connexion.middleware.lifespan import Lifespan
|
||||
from connexion.operations import AbstractOperation
|
||||
from connexion.options import SwaggerUIOptions
|
||||
from connexion.resolver import Resolver
|
||||
from connexion.uri_parsing import AbstractURIParser
|
||||
|
||||
@@ -131,7 +132,7 @@ class AsyncApp(AbstractApp):
|
||||
resolver: t.Optional[t.Union[Resolver, t.Callable]] = None,
|
||||
resolver_error: t.Optional[int] = None,
|
||||
strict_validation: t.Optional[bool] = None,
|
||||
swagger_ui_options: t.Optional[dict] = None,
|
||||
swagger_ui_options: t.Optional[SwaggerUIOptions] = None,
|
||||
uri_parser_class: t.Optional[AbstractURIParser] = None,
|
||||
validate_responses: t.Optional[bool] = None,
|
||||
validator_map: t.Optional[dict] = None,
|
||||
@@ -161,8 +162,8 @@ class AsyncApp(AbstractApp):
|
||||
start.
|
||||
:param strict_validation: When True, extra form or query parameters not defined in the
|
||||
specification result in a validation error. Defaults to False.
|
||||
:param swagger_ui_options: A dict with configuration options for the swagger ui. See
|
||||
:class:`options.ConnexionOptions`.
|
||||
:param swagger_ui_options: Instance of :class:`options.ConnexionOptions` with
|
||||
configuration options for the swagger ui.
|
||||
:param uri_parser_class: Class to use for uri parsing. See :mod:`uri_parsing`.
|
||||
:param validate_responses: Whether to validate responses against the specification. This has
|
||||
an impact on performance. Defaults to False.
|
||||
|
||||
@@ -20,6 +20,7 @@ from connexion.jsonifier import Jsonifier
|
||||
from connexion.middleware.abstract import AbstractRoutingAPI, SpecMiddleware
|
||||
from connexion.middleware.lifespan import Lifespan
|
||||
from connexion.operations import AbstractOperation
|
||||
from connexion.options import SwaggerUIOptions
|
||||
from connexion.problem import problem
|
||||
from connexion.resolver import Resolver
|
||||
from connexion.uri_parsing import AbstractURIParser
|
||||
@@ -188,7 +189,7 @@ class FlaskApp(AbstractApp):
|
||||
resolver: t.Optional[t.Union[Resolver, t.Callable]] = None,
|
||||
resolver_error: t.Optional[int] = None,
|
||||
strict_validation: t.Optional[bool] = None,
|
||||
swagger_ui_options: t.Optional[dict] = None,
|
||||
swagger_ui_options: t.Optional[SwaggerUIOptions] = None,
|
||||
uri_parser_class: t.Optional[AbstractURIParser] = None,
|
||||
validate_responses: t.Optional[bool] = None,
|
||||
validator_map: t.Optional[dict] = None,
|
||||
@@ -221,8 +222,8 @@ class FlaskApp(AbstractApp):
|
||||
start.
|
||||
:param strict_validation: When True, extra form or query parameters not defined in the
|
||||
specification result in a validation error. Defaults to False.
|
||||
:param swagger_ui_options: A dict with configuration options for the swagger ui. See
|
||||
:class:`options.ConnexionOptions`.
|
||||
:param swagger_ui_options: Instance of :class:`options.ConnexionOptions` with
|
||||
configuration options for the swagger ui.
|
||||
:param uri_parser_class: Class to use for uri parsing. See :mod:`uri_parsing`.
|
||||
:param validate_responses: Whether to validate responses against the specification. This has
|
||||
an impact on performance. Defaults to False.
|
||||
|
||||
@@ -8,12 +8,16 @@ import sys
|
||||
from os import path
|
||||
|
||||
import click
|
||||
import importlib_metadata
|
||||
from clickclick import AliasedGroup
|
||||
|
||||
import connexion
|
||||
from connexion.mock import MockResolver
|
||||
|
||||
try:
|
||||
import importlib_metadata
|
||||
except ImportError:
|
||||
import importlib.metadata as importlib_metadata # type: ignore
|
||||
|
||||
logger = logging.getLogger("connexion.cli")
|
||||
|
||||
FLASK_APP = "flask"
|
||||
|
||||
@@ -21,6 +21,7 @@ from connexion.middleware.response_validation import ResponseValidationMiddlewar
|
||||
from connexion.middleware.routing import RoutingMiddleware
|
||||
from connexion.middleware.security import SecurityMiddleware
|
||||
from connexion.middleware.swagger_ui import SwaggerUIMiddleware
|
||||
from connexion.options import SwaggerUIOptions
|
||||
from connexion.resolver import Resolver
|
||||
from connexion.uri_parsing import AbstractURIParser
|
||||
from connexion.utils import inspect_function_arguments
|
||||
@@ -51,7 +52,7 @@ class _Options:
|
||||
resolver_error: t.Optional[int] = None
|
||||
resolver_error_handler: t.Optional[t.Callable] = field(init=False)
|
||||
strict_validation: t.Optional[bool] = False
|
||||
swagger_ui_options: t.Optional[dict] = None
|
||||
swagger_ui_options: t.Optional[SwaggerUIOptions] = None
|
||||
uri_parser_class: t.Optional[AbstractURIParser] = None
|
||||
validate_responses: t.Optional[bool] = False
|
||||
validator_map: t.Optional[dict] = None
|
||||
@@ -186,7 +187,7 @@ class ConnexionMiddleware:
|
||||
resolver: t.Optional[t.Union[Resolver, t.Callable]] = None,
|
||||
resolver_error: t.Optional[int] = None,
|
||||
strict_validation: t.Optional[bool] = None,
|
||||
swagger_ui_options: t.Optional[dict] = None,
|
||||
swagger_ui_options: t.Optional[SwaggerUIOptions] = None,
|
||||
uri_parser_class: t.Optional[AbstractURIParser] = None,
|
||||
validate_responses: t.Optional[bool] = None,
|
||||
validator_map: t.Optional[dict] = None,
|
||||
@@ -214,8 +215,8 @@ class ConnexionMiddleware:
|
||||
start.
|
||||
:param strict_validation: When True, extra form or query parameters not defined in the
|
||||
specification result in a validation error. Defaults to False.
|
||||
:param swagger_ui_options: A dict with configuration options for the swagger ui. See
|
||||
:class:`options.ConnexionOptions`.
|
||||
:param swagger_ui_options: Instance of :class:`options.ConnexionOptions` with
|
||||
configuration options for the swagger ui.
|
||||
:param uri_parser_class: Class to use for uri parsing. See :mod:`uri_parsing`.
|
||||
:param validate_responses: Whether to validate responses against the specification. This has
|
||||
an impact on performance. Defaults to False.
|
||||
@@ -338,7 +339,7 @@ class ConnexionMiddleware:
|
||||
resolver: t.Optional[t.Union[Resolver, t.Callable]] = None,
|
||||
resolver_error: t.Optional[int] = None,
|
||||
strict_validation: t.Optional[bool] = None,
|
||||
swagger_ui_options: t.Optional[dict] = None,
|
||||
swagger_ui_options: t.Optional[SwaggerUIOptions] = None,
|
||||
uri_parser_class: t.Optional[AbstractURIParser] = None,
|
||||
validate_responses: t.Optional[bool] = None,
|
||||
validator_map: t.Optional[dict] = None,
|
||||
|
||||
@@ -16,7 +16,7 @@ from starlette.types import ASGIApp, Receive, Scope, Send
|
||||
from connexion.jsonifier import Jsonifier
|
||||
from connexion.middleware import SpecMiddleware
|
||||
from connexion.middleware.abstract import AbstractSpecAPI
|
||||
from connexion.options import SwaggerUIOptions
|
||||
from connexion.options import SwaggerUIConfig, SwaggerUIOptions
|
||||
from connexion.utils import yamldumper
|
||||
|
||||
logger = logging.getLogger("connexion.middleware.swagger_ui")
|
||||
@@ -30,13 +30,13 @@ class SwaggerUIAPI(AbstractSpecAPI):
|
||||
self,
|
||||
*args,
|
||||
default: ASGIApp,
|
||||
swagger_ui_options: t.Optional[dict] = None,
|
||||
swagger_ui_options: t.Optional[SwaggerUIOptions] = None,
|
||||
**kwargs
|
||||
):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.router = Router(default=default)
|
||||
self.options = SwaggerUIOptions(
|
||||
self.options = SwaggerUIConfig(
|
||||
swagger_ui_options, oas_version=self.specification.version
|
||||
)
|
||||
|
||||
@@ -44,11 +44,11 @@ class SwaggerUIAPI(AbstractSpecAPI):
|
||||
self.add_openapi_json()
|
||||
self.add_openapi_yaml()
|
||||
|
||||
if self.options.openapi_console_ui_available:
|
||||
if self.options.swagger_ui_available:
|
||||
self.add_swagger_ui()
|
||||
|
||||
self._templates = Jinja2Templates(
|
||||
directory=str(self.options.openapi_console_ui_from_dir)
|
||||
directory=str(self.options.swagger_ui_template_dir)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@@ -121,7 +121,7 @@ class SwaggerUIAPI(AbstractSpecAPI):
|
||||
"""
|
||||
Adds swagger ui to {base_path}/ui/
|
||||
"""
|
||||
console_ui_path = self.options.openapi_console_ui_path.strip().rstrip("/")
|
||||
console_ui_path = self.options.swagger_ui_path.strip().rstrip("/")
|
||||
logger.debug("Adding swagger-ui: %s%s/", self.base_path, console_ui_path)
|
||||
|
||||
for path in (
|
||||
@@ -132,7 +132,7 @@ class SwaggerUIAPI(AbstractSpecAPI):
|
||||
methods=["GET"], path=path, endpoint=self._get_swagger_ui_home
|
||||
)
|
||||
|
||||
if self.options.openapi_console_ui_config is not None:
|
||||
if self.options.swagger_ui_config:
|
||||
self.router.add_route(
|
||||
methods=["GET"],
|
||||
path=console_ui_path + "/swagger-ui-config.json",
|
||||
@@ -155,7 +155,7 @@ class SwaggerUIAPI(AbstractSpecAPI):
|
||||
# serve index.html, so we add the redirect above.
|
||||
self.router.mount(
|
||||
path=console_ui_path,
|
||||
app=StaticFiles(directory=str(self.options.openapi_console_ui_from_dir)),
|
||||
app=StaticFiles(directory=str(self.options.swagger_ui_template_dir)),
|
||||
name="swagger_ui_static",
|
||||
)
|
||||
|
||||
@@ -164,9 +164,9 @@ class SwaggerUIAPI(AbstractSpecAPI):
|
||||
template_variables = {
|
||||
"request": req,
|
||||
"openapi_spec_url": (base_path + self.options.openapi_spec_path),
|
||||
**self.options.openapi_console_ui_index_template_variables,
|
||||
**self.options.swagger_ui_template_arguments,
|
||||
}
|
||||
if self.options.openapi_console_ui_config is not None:
|
||||
if self.options.swagger_ui_config:
|
||||
template_variables["configUrl"] = "swagger-ui-config.json"
|
||||
|
||||
return self._templates.TemplateResponse("index.j2", template_variables)
|
||||
@@ -175,7 +175,7 @@ class SwaggerUIAPI(AbstractSpecAPI):
|
||||
return StarletteResponse(
|
||||
status_code=200,
|
||||
media_type="application/json",
|
||||
content=json.dumps(self.options.openapi_console_ui_config),
|
||||
content=json.dumps(self.options.swagger_ui_config),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
"""
|
||||
This module defines a Connexion specific options class to pass to the Connexion App or API.
|
||||
"""
|
||||
|
||||
import dataclasses
|
||||
import logging
|
||||
from typing import Optional # NOQA
|
||||
import typing as t
|
||||
|
||||
try:
|
||||
from py_swagger_ui import swagger_ui_path
|
||||
from py_swagger_ui import swagger_ui_path as default_template_dir
|
||||
except ImportError:
|
||||
swagger_ui_path = None
|
||||
default_template_dir = None
|
||||
|
||||
NO_UI_MSG = """The swagger_ui directory could not be found.
|
||||
Please install connexion with extra install: pip install connexion[swagger-ui]
|
||||
@@ -18,131 +18,82 @@ NO_UI_MSG = """The swagger_ui directory could not be found.
|
||||
logger = logging.getLogger("connexion.options")
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class SwaggerUIOptions:
|
||||
"""Options to configure the Swagger UI.
|
||||
|
||||
:param serve_spec: Whether to serve the Swagger / OpenAPI Specification
|
||||
:param spec_path: Where to serve the Swagger / OpenAPI Specification
|
||||
|
||||
:param swagger_ui: Whether to serve the Swagger UI
|
||||
:param swagger_ui_path: Where to serve the Swagger UI
|
||||
:param swagger_ui_config: Options to configure the Swagger UI. See
|
||||
https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration
|
||||
for an overview of the available options.
|
||||
:param swagger_ui_template_dir: Directory with static files to use to serve Swagger UI
|
||||
:param swagger_ui_template_arguments: Arguments passed to the Swagger UI template. Useful
|
||||
when providing your own template dir with additional template arguments.
|
||||
"""
|
||||
|
||||
serve_spec: bool = True
|
||||
spec_path: t.Optional[str] = None
|
||||
|
||||
swagger_ui: bool = True
|
||||
swagger_ui_config: dict = dataclasses.field(default_factory=dict)
|
||||
swagger_ui_path: str = "/ui"
|
||||
swagger_ui_template_dir: t.Optional[str] = None
|
||||
swagger_ui_template_arguments: dict = dataclasses.field(default_factory=dict)
|
||||
|
||||
|
||||
class SwaggerUIConfig:
|
||||
"""Class holding swagger UI specific options."""
|
||||
|
||||
def __init__(self, options=None, oas_version=(2,)):
|
||||
self._options = {}
|
||||
self.oas_version = oas_version
|
||||
self.swagger_ui_local_path = swagger_ui_path
|
||||
if self.oas_version >= (3, 0, 0):
|
||||
self.openapi_spec_name = "/openapi.json"
|
||||
def __init__(
|
||||
self,
|
||||
options: t.Optional[SwaggerUIOptions] = None,
|
||||
oas_version: t.Tuple[int, ...] = (2,),
|
||||
):
|
||||
if oas_version >= (3, 0, 0):
|
||||
self.spec_path = "/openapi.json"
|
||||
else:
|
||||
self.openapi_spec_name = "/swagger.json"
|
||||
self.spec_path = "/swagger.json"
|
||||
|
||||
if options:
|
||||
self._options.update(filter_values(options))
|
||||
|
||||
def extend(self, new_values=None):
|
||||
# type: (Optional[dict]) -> SwaggerUIOptions
|
||||
"""
|
||||
Return a new instance of `ConnexionOptions` using as default the currently
|
||||
defined options.
|
||||
"""
|
||||
if new_values is None:
|
||||
new_values = {}
|
||||
|
||||
options = dict(self._options)
|
||||
options.update(filter_values(new_values))
|
||||
return SwaggerUIOptions(options, self.oas_version)
|
||||
|
||||
def as_dict(self):
|
||||
return self._options
|
||||
self._options = options or SwaggerUIOptions()
|
||||
|
||||
@property
|
||||
def openapi_spec_available(self):
|
||||
# type: () -> bool
|
||||
"""
|
||||
Whether to make available the OpenAPI Specification under
|
||||
`openapi_spec_path`.
|
||||
|
||||
Default: True
|
||||
"""
|
||||
deprecated_option = self._options.get("swagger_json", True)
|
||||
serve_spec = self._options.get("serve_spec", deprecated_option)
|
||||
if "swagger_json" in self._options:
|
||||
deprecation_warning = (
|
||||
"The 'swagger_json' option is deprecated. "
|
||||
"Please use 'serve_spec' instead"
|
||||
)
|
||||
logger.warning(deprecation_warning)
|
||||
return serve_spec
|
||||
def openapi_spec_available(self) -> bool:
|
||||
"""Whether to make the OpenAPI Specification available."""
|
||||
return self._options.serve_spec
|
||||
|
||||
@property
|
||||
def openapi_console_ui_available(self):
|
||||
# type: () -> bool
|
||||
"""
|
||||
Whether to make the OpenAPI Console UI available under the path
|
||||
defined in `openapi_console_ui_path` option.
|
||||
def openapi_spec_path(self) -> str:
|
||||
"""Path to host the Swagger UI."""
|
||||
return self._options.spec_path or self.spec_path
|
||||
|
||||
Default: True
|
||||
"""
|
||||
if (
|
||||
self._options.get("swagger_ui", True)
|
||||
and self.openapi_console_ui_from_dir is None
|
||||
):
|
||||
@property
|
||||
def swagger_ui_available(self) -> bool:
|
||||
"""Whether to make the Swagger UI available."""
|
||||
if self._options.swagger_ui and self.swagger_ui_template_dir is None:
|
||||
logger.warning(NO_UI_MSG)
|
||||
return False
|
||||
return self._options.get("swagger_ui", True)
|
||||
return self._options.swagger_ui
|
||||
|
||||
@property
|
||||
def openapi_spec_path(self):
|
||||
# type: () -> str
|
||||
"""
|
||||
Path to mount the OpenAPI Console UI and make it accessible via a browser.
|
||||
|
||||
Default: /openapi.json for openapi3, otherwise /swagger.json
|
||||
"""
|
||||
return self._options.get("openapi_spec_path", self.openapi_spec_name)
|
||||
def swagger_ui_path(self) -> str:
|
||||
"""Path to mount the Swagger UI and make it accessible via a browser."""
|
||||
return self._options.swagger_ui_path
|
||||
|
||||
@property
|
||||
def openapi_console_ui_path(self):
|
||||
# type: () -> str
|
||||
"""
|
||||
Path to mount the OpenAPI Console UI and make it accessible via a browser.
|
||||
|
||||
Default: /ui
|
||||
"""
|
||||
return self._options.get("swagger_url", "/ui")
|
||||
def swagger_ui_template_dir(self) -> str:
|
||||
"""Directory with static files to use to serve Swagger UI."""
|
||||
return self._options.swagger_ui_template_dir or default_template_dir
|
||||
|
||||
@property
|
||||
def openapi_console_ui_from_dir(self):
|
||||
# type: () -> str
|
||||
"""
|
||||
Custom OpenAPI Console UI directory from where Connexion will serve
|
||||
the static files.
|
||||
|
||||
Default: Connexion's vendored version of the OpenAPI Console UI.
|
||||
"""
|
||||
return self._options.get("swagger_path", self.swagger_ui_local_path)
|
||||
def swagger_ui_config(self) -> dict:
|
||||
"""Options to configure the Swagger UI."""
|
||||
return self._options.swagger_ui_config
|
||||
|
||||
@property
|
||||
def openapi_console_ui_config(self):
|
||||
# type: () -> dict
|
||||
"""
|
||||
Custom OpenAPI Console UI config.
|
||||
|
||||
Default: None
|
||||
"""
|
||||
return self._options.get("swagger_ui_config", None)
|
||||
|
||||
@property
|
||||
def openapi_console_ui_index_template_variables(self):
|
||||
# type: () -> dict
|
||||
"""
|
||||
Custom variables passed to the OpenAPI Console UI template.
|
||||
|
||||
Default: {}
|
||||
"""
|
||||
return self._options.get("swagger_ui_template_arguments", {})
|
||||
|
||||
|
||||
def filter_values(dictionary):
|
||||
# type: (dict) -> dict
|
||||
"""
|
||||
Remove `None` value entries in the dictionary.
|
||||
|
||||
:param dictionary:
|
||||
:return:
|
||||
"""
|
||||
return {key: value for key, value in dictionary.items() if value is not None}
|
||||
def swagger_ui_template_arguments(self) -> dict:
|
||||
"""Arguments passed to the Swagger UI template."""
|
||||
return self._options.swagger_ui_template_arguments
|
||||
|
||||
@@ -64,8 +64,9 @@ Documentation
|
||||
|
||||
quickstart
|
||||
middleware
|
||||
cli
|
||||
routing
|
||||
swagger_ui
|
||||
cli
|
||||
request
|
||||
response
|
||||
security
|
||||
|
||||
@@ -236,10 +236,12 @@ If you installed connexion using the :code:`swagger-ui` extra, a Swagger UI is a
|
||||
API, providing interactive documentation. By default the UI is hosted at :code:`{base_path}/ui/`
|
||||
where :code:`base_path`` is the base path of the API.
|
||||
|
||||
**https://localhost:{port}/{base_path}/ui/**
|
||||
**https://{host}/{base_path}/ui/**
|
||||
|
||||
.. image:: images/swagger_ui.png
|
||||
|
||||
Check :doc:`swagger_ui` for information on how to configure the UI.
|
||||
|
||||
Full App class reference
|
||||
------------------------
|
||||
|
||||
|
||||
71
docs/swagger_ui.rst
Normal file
71
docs/swagger_ui.rst
Normal file
@@ -0,0 +1,71 @@
|
||||
The Swagger UI
|
||||
==============
|
||||
|
||||
If you installed connexion using the :code:`swagger-ui` extra, a Swagger UI is available for each
|
||||
API, providing interactive documentation. By default the UI is hosted at :code:`{base_path}/ui/`
|
||||
where :code:`base_path`` is the base path of the API.
|
||||
|
||||
**https://{host}/{base_path}/ui/**
|
||||
|
||||
.. image:: images/swagger_ui.png
|
||||
|
||||
Configuring the Swagger UI
|
||||
--------------------------
|
||||
|
||||
You can change this path through the ``swagger_ui_options`` argument, either whe instantiating
|
||||
your application, or when adding your api:
|
||||
|
||||
|
||||
.. tab-set::
|
||||
|
||||
.. tab-item:: AsyncApp
|
||||
:sync: AsyncApp
|
||||
|
||||
.. code-block:: python
|
||||
:caption: **app.py**
|
||||
|
||||
from connexion import AsyncApp
|
||||
from connexion.options import SwaggerUIOptions
|
||||
|
||||
options = SwaggerUIOptions(swagger_ui_path="/docs")
|
||||
|
||||
app = AsyncApp(__name__, swagger_ui_options=options)
|
||||
app.add_api("openapi.yaml", swagger_ui_options=options)
|
||||
|
||||
.. tab-item:: FlaskApp
|
||||
:sync: FlaskApp
|
||||
|
||||
.. code-block:: python
|
||||
:caption: **app.py**
|
||||
|
||||
from connexion import FlaskApp
|
||||
from connexion.options import SwaggerUIOptions
|
||||
|
||||
options = SwaggerUIOptions(swagger_ui_path="/docs")
|
||||
|
||||
app = FlaskApp(__name__, swagger_ui_options=options)
|
||||
app.add_api("openapi.yaml", swagger_ui_options=options)
|
||||
|
||||
.. tab-item:: ConnexionMiddleware
|
||||
:sync: ConnexionMiddleware
|
||||
|
||||
.. code-block:: python
|
||||
:caption: **app.py**
|
||||
|
||||
from asgi_framework import App
|
||||
from connexion import ConnexionMiddleware
|
||||
from connexion.options import SwaggerUIOptions
|
||||
|
||||
options = SwaggerUIOptions(swagger_ui_path="/docs")
|
||||
|
||||
app = App(__name__)
|
||||
app = ConnexionMiddleware(app, swagger_ui_options=options)
|
||||
app.add_api("openapi.yaml", swagger_ui_options=options):
|
||||
|
||||
For a description of all available options, check the :class:`.SwaggerUIOptions`
|
||||
class.
|
||||
|
||||
.. dropdown:: View a detailed reference of the :code:`SwaggerUIOptions` class
|
||||
:icon: eye
|
||||
|
||||
.. autoclass:: connexion.options.SwaggerUIOptions
|
||||
@@ -105,7 +105,9 @@ should work, connexion comes with ``uvicorn`` as an extra:
|
||||
Smaller breaking changes
|
||||
------------------------
|
||||
|
||||
* The ``options`` argument has been renamed to ``swagger_ui_options``
|
||||
* The ``options`` argument has been renamed to ``swagger_ui_options`` and now takes an instance
|
||||
of the :class:`.SwaggerUIOptions`. The naming of the options themselves have been changed to
|
||||
better represent their meaning.
|
||||
* The ``uri_parser_class`` is now passed to the ``App`` or its ``add_api()`` method directly
|
||||
instead of via the ``options`` argument.
|
||||
* The ``jsonifier`` is now passed to the ``App`` or its ``add_api()`` method instead of setting it
|
||||
|
||||
@@ -8,6 +8,7 @@ from connexion.exceptions import InvalidSpecification
|
||||
from connexion.http_facts import METHODS
|
||||
from connexion.json_schema import ExtendedSafeLoader
|
||||
from connexion.middleware.abstract import AbstractRoutingAPI
|
||||
from connexion.options import SwaggerUIOptions
|
||||
|
||||
from conftest import TEST_FOLDER, build_app_from_fixture
|
||||
|
||||
@@ -57,7 +58,7 @@ def test_swagger_ui(simple_api_spec_dir, spec):
|
||||
|
||||
def test_swagger_ui_with_config(simple_api_spec_dir, spec):
|
||||
swagger_ui_config = {"displayOperationId": True}
|
||||
swagger_ui_options = {"swagger_ui_config": swagger_ui_config}
|
||||
swagger_ui_options = SwaggerUIOptions(swagger_ui_config=swagger_ui_config)
|
||||
app = App(
|
||||
__name__,
|
||||
specification_dir=simple_api_spec_dir,
|
||||
@@ -72,7 +73,7 @@ def test_swagger_ui_with_config(simple_api_spec_dir, spec):
|
||||
|
||||
|
||||
def test_no_swagger_ui(simple_api_spec_dir, spec):
|
||||
swagger_ui_options = {"swagger_ui": False}
|
||||
swagger_ui_options = SwaggerUIOptions(swagger_ui=False)
|
||||
app = App(
|
||||
__name__,
|
||||
specification_dir=simple_api_spec_dir,
|
||||
@@ -85,7 +86,7 @@ def test_no_swagger_ui(simple_api_spec_dir, spec):
|
||||
assert swagger_ui.status_code == 404
|
||||
|
||||
app2 = App(__name__, specification_dir=simple_api_spec_dir)
|
||||
app2.add_api(spec, swagger_ui_options={"swagger_ui": False})
|
||||
app2.add_api(spec, swagger_ui_options=SwaggerUIOptions(swagger_ui=False))
|
||||
app2_client = app2.test_client()
|
||||
swagger_ui2 = app2_client.get("/v1.0/ui/")
|
||||
assert swagger_ui2.status_code == 404
|
||||
@@ -94,7 +95,7 @@ def test_no_swagger_ui(simple_api_spec_dir, spec):
|
||||
def test_swagger_ui_config_json(simple_api_spec_dir, spec):
|
||||
"""Verify the swagger-ui-config.json file is returned for swagger_ui_config option passed to app."""
|
||||
swagger_ui_config = {"displayOperationId": True}
|
||||
swagger_ui_options = {"swagger_ui_config": swagger_ui_config}
|
||||
swagger_ui_options = SwaggerUIOptions(swagger_ui_config=swagger_ui_config)
|
||||
app = App(
|
||||
__name__,
|
||||
specification_dir=simple_api_spec_dir,
|
||||
@@ -142,7 +143,7 @@ def test_swagger_yaml_app(simple_api_spec_dir, spec):
|
||||
|
||||
def test_no_swagger_json_app(simple_api_spec_dir, spec):
|
||||
"""Verify the spec json file is not returned when set to False when creating app."""
|
||||
swagger_ui_options = {"serve_spec": False}
|
||||
swagger_ui_options = SwaggerUIOptions(serve_spec=False)
|
||||
app = App(
|
||||
__name__,
|
||||
specification_dir=simple_api_spec_dir,
|
||||
@@ -193,7 +194,7 @@ def test_swagger_json_api(simple_api_spec_dir, spec):
|
||||
def test_no_swagger_json_api(simple_api_spec_dir, spec):
|
||||
"""Verify the spec json file is not returned when set to False when adding api."""
|
||||
app = App(__name__, specification_dir=simple_api_spec_dir)
|
||||
app.add_api(spec, swagger_ui_options={"serve_spec": False})
|
||||
app.add_api(spec, swagger_ui_options=SwaggerUIOptions(serve_spec=False))
|
||||
|
||||
app_client = app.test_client()
|
||||
url = "/v1.0/{spec}".format(spec=spec.replace("yaml", "json"))
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import logging
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import importlib_metadata
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
from connexion.cli import main
|
||||
@@ -9,6 +8,11 @@ from connexion.exceptions import ResolverError
|
||||
|
||||
from conftest import FIXTURES_FOLDER
|
||||
|
||||
try:
|
||||
import importlib_metadata
|
||||
except ImportError:
|
||||
import importlib.metadata as importlib_metadata
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def mock_app_run(app_class, monkeypatch):
|
||||
|
||||
Reference in New Issue
Block a user