OpenAPI integration#
This guide shows how to integrate OpenAPI with RESTAlchemy APIs.
We will:
- Create an API with OpenAPI routes.
- Use
OpenApiApplicationandOpenApiSpecificationRoute. - Annotate controllers with OpenAPI schemas.
- Fetch the OpenAPI specification.
The example is based on examples/openapi_app.py.
1. DM model#
from restalchemy.dm import models, properties, types
class FileModel(models.ModelWithUUID):
name = properties.property(types.String(), required=True)
2. Controller with OpenAPI annotations#
Module: restalchemy.openapi.utils and restalchemy.openapi.constants are used for schemas.
from restalchemy.api import actions, constants, controllers, resources
from restalchemy.openapi import engines as openapi_engines
from restalchemy.openapi import structures as openapi_structures
from restalchemy.openapi import utils as oa_utils
from restalchemy.openapi import constants as oa_c
class FilesController(controllers.Controller):
"""Controller for /v1/files/[<id>] endpoint."""
__resource__ = resources.ResourceByRAModel(
model_class=FileModel,
process_filters=True,
convert_underscore=False,
)
def create(self, **kwargs):
# Implement file upload logic here
pass
create.openapi_schema = oa_utils.Schema(
summary="Upload file",
parameters=(),
responses=oa_c.build_openapi_create_response(
"%s_Create" % __resource__.get_model().__name__
),
request_body=oa_c.build_openapi_req_body_multipart(
description="Upload file to docs set",
properties={"file": {"format": "binary", "type": "string"}},
),
)
@oa_utils.extend_schema(
summary="Download file",
parameters=(),
responses=oa_c.build_openapi_response_octet_stream(),
)
@actions.get
def download(self, resource, **kwargs):
data = resource.download_file()
headers = {
"Content-Type": constants.CONTENT_TYPE_OCTET_STREAM,
"Content-Disposition": f'attachment; filename="{resource.name}"',
}
return data, 200, headers
download.openapi_schema = oa_utils.Schema(
summary="Download file",
parameters=(),
responses=oa_c.build_openapi_response_octet_stream(),
)
Key points:
oa_utils.Schemaobjects attached to controller methods describe:summary,parameters,responses,request_body,tags.@oa_utils.extend_schemais a decorator variant for actions.- If you do not provide schemas, RA will generate reasonable defaults based on resources and DM types.
3. Routes and OpenAPI specification route#
from restalchemy.api import routes
class FileDownloadAction(routes.Action):
"""Handler for /v1/files/<id>/actions/download endpoint."""
__controller__ = FilesController
class FilesRoute(routes.Route):
"""Handler for /v1/files/<id> endpoint."""
__controller__ = FilesController
__allow_methods__ = [
routes.CREATE,
routes.DELETE,
routes.FILTER,
routes.GET,
routes.UPDATE,
]
download = routes.action(FileDownloadAction, invoke=True)
class ApiEndpointController(controllers.RoutesListController):
"""Controller for /v1/ endpoint."""
__TARGET_PATH__ = "/v1/"
class ApiEndpointRoute(routes.Route):
"""Handler for /v1/ endpoint."""
__controller__ = ApiEndpointController
__allow_methods__ = [routes.FILTER, routes.GET]
specifications = routes.action(routes.OpenApiSpecificationRoute)
files = routes.route(FilesRoute)
class UserApiApp(routes.RootRoute):
__controller__ = controllers.RootController
__allow_methods__ = [routes.FILTER]
setattr(UserApiApp, "v1", routes.route(ApiEndpointRoute))
OpenApiSpecificationRouteis a built-in route that exposes OpenAPI specs.ApiEndpointRoute.specificationsattaches it under/v1/specifications/.
4. OpenAPI engine and application#
from restalchemy.api import applications, middlewares
def get_openapi_engine():
openapi_engine = openapi_engines.OpenApiEngine(
info=openapi_structures.OpenApiInfo(),
paths=openapi_structures.OpenApiPaths(),
components=openapi_structures.OpenApiComponents(),
)
return openapi_engine
def get_user_api_application():
return UserApiApp
def build_wsgi_application():
return middlewares.attach_middlewares(
applications.OpenApiApplication(
route_class=get_user_api_application(),
openapi_engine=get_openapi_engine(),
),
[],
)
OpenApiApplicationextendsWSGIAppwith anopenapi_engineproperty.OpenApiSpecificationControlleruses this engine to build the spec.
5. Fetching the OpenAPI spec#
After starting the application, you can fetch the spec:
- The path version (
3.0.3) corresponds to the OpenAPI version requested. - The response is a JSON OpenAPI document.
You can plug this URL into tools like Swagger UI or code generators.
Summary#
- Use
OpenApiApplicationandOpenApiSpecificationRouteto expose OpenAPI. - Annotate controller methods with
oa_utils.Schemaor@extend_schemawhen you need fine control. - Otherwise, rely on RA's defaults derived from resources and DM types.