diff --git a/aws_lambda_powertools/event_handler/api_gateway.py b/aws_lambda_powertools/event_handler/api_gateway.py index be74ece69ea..17b8da641d3 100644 --- a/aws_lambda_powertools/event_handler/api_gateway.py +++ b/aws_lambda_powertools/event_handler/api_gateway.py @@ -85,6 +85,7 @@ ) from aws_lambda_powertools.event_handler.openapi.models import ( Contact, + ExternalDocumentation, License, OpenAPI, SecurityScheme, @@ -1714,6 +1715,7 @@ def get_openapi_schema( license_info: License | None = None, security_schemes: dict[str, SecurityScheme] | None = None, security: list[dict[str, list[str]]] | None = None, + external_documentation: ExternalDocumentation | None = None, openapi_extensions: dict[str, Any] | None = None, ) -> OpenAPI: """ @@ -1745,6 +1747,8 @@ def get_openapi_schema( A declaration of the security schemes available to be used in the specification. security: list[dict[str, list[str]]], optional A declaration of which security mechanisms are applied globally across the API. + external_documentation: ExternalDocumentation, optional + Additional external documentation for the API. openapi_extensions: Dict[str, Any], optional Additional OpenAPI extensions as a dictionary. @@ -1775,6 +1779,7 @@ def get_openapi_schema( license_info = license_info or self.openapi_config.license_info security_schemes = security_schemes or self.openapi_config.security_schemes security = security or self.openapi_config.security + external_documentation = external_documentation or self.openapi_config.external_documentation openapi_extensions = openapi_extensions or self.openapi_config.openapi_extensions from pydantic.json_schema import GenerateJsonSchema @@ -1814,6 +1819,9 @@ def get_openapi_schema( **openapi_extensions, } + if external_documentation: + output["externalDocs"] = external_documentation + components: dict[str, dict[str, Any]] = {} paths: dict[str, dict[str, Any]] = {} operation_ids: set[str] = set() @@ -1921,6 +1929,7 @@ def get_openapi_json_schema( license_info: License | None = None, security_schemes: dict[str, SecurityScheme] | None = None, security: list[dict[str, list[str]]] | None = None, + external_documentation: ExternalDocumentation | None = None, openapi_extensions: dict[str, Any] | None = None, ) -> str: """ @@ -1952,6 +1961,8 @@ def get_openapi_json_schema( A declaration of the security schemes available to be used in the specification. security: list[dict[str, list[str]]], optional A declaration of which security mechanisms are applied globally across the API. + external_documentation: ExternalDocumentation, optional + Additional external documentation for the API. openapi_extensions: Dict[str, Any], optional Additional OpenAPI extensions as a dictionary. @@ -1977,6 +1988,7 @@ def get_openapi_json_schema( license_info=license_info, security_schemes=security_schemes, security=security, + external_documentation=external_documentation, openapi_extensions=openapi_extensions, ), by_alias=True, @@ -1998,6 +2010,7 @@ def configure_openapi( license_info: License | None = None, security_schemes: dict[str, SecurityScheme] | None = None, security: list[dict[str, list[str]]] | None = None, + external_documentation: ExternalDocumentation | None = None, openapi_extensions: dict[str, Any] | None = None, ): """Configure OpenAPI specification settings for the API. @@ -2031,6 +2044,8 @@ def configure_openapi( A declaration of the security schemes available to be used in the specification. security: list[dict[str, list[str]]], optional A declaration of which security mechanisms are applied globally across the API. + external_documentation: ExternalDocumentation, optional + A link to external documentation for the API. openapi_extensions: Dict[str, Any], optional Additional OpenAPI extensions as a dictionary. @@ -2064,6 +2079,7 @@ def configure_openapi( license_info=license_info, security_schemes=security_schemes, security=security, + external_documentation=external_documentation, openapi_extensions=openapi_extensions, ) @@ -2088,6 +2104,7 @@ def enable_swagger( security: list[dict[str, list[str]]] | None = None, oauth2_config: OAuth2Config | None = None, persist_authorization: bool = False, + external_documentation: ExternalDocumentation | None = None, openapi_extensions: dict[str, Any] | None = None, ): """ @@ -2131,6 +2148,8 @@ def enable_swagger( The OAuth2 configuration for the Swagger UI. persist_authorization: bool, optional Whether to persist authorization data on browser close/refresh. + external_documentation: ExternalDocumentation, optional + A link to external documentation for the API. openapi_extensions: dict[str, Any], optional Additional OpenAPI extensions as a dictionary. """ @@ -2183,6 +2202,7 @@ def swagger_handler(): license_info=license_info, security_schemes=security_schemes, security=security, + external_documentation=external_documentation, openapi_extensions=openapi_extensions, ) diff --git a/aws_lambda_powertools/event_handler/openapi/config.py b/aws_lambda_powertools/event_handler/openapi/config.py index 597362d1ef9..83fe2156a57 100644 --- a/aws_lambda_powertools/event_handler/openapi/config.py +++ b/aws_lambda_powertools/event_handler/openapi/config.py @@ -12,6 +12,7 @@ if TYPE_CHECKING: from aws_lambda_powertools.event_handler.openapi.models import ( Contact, + ExternalDocumentation, License, SecurityScheme, Server, @@ -51,6 +52,8 @@ class OpenAPIConfig: A declaration of the security schemes available to be used in the specification. security: list[dict[str, list[str]]], optional A declaration of which security mechanisms are applied globally across the API. + external_documentation: ExternalDocumentation, optional + A link to external documentation for the API. openapi_extensions: Dict[str, Any], optional Additional OpenAPI extensions as a dictionary. @@ -77,4 +80,5 @@ class OpenAPIConfig: license_info: License | None = None security_schemes: dict[str, SecurityScheme] | None = None security: list[dict[str, list[str]]] | None = None + external_documentation: ExternalDocumentation | None = None openapi_extensions: dict[str, Any] | None = None diff --git a/tests/functional/event_handler/_pydantic/test_openapi_external_documentation.py b/tests/functional/event_handler/_pydantic/test_openapi_external_documentation.py new file mode 100644 index 00000000000..680e998b8bd --- /dev/null +++ b/tests/functional/event_handler/_pydantic/test_openapi_external_documentation.py @@ -0,0 +1,28 @@ +from __future__ import annotations + +from aws_lambda_powertools.event_handler.api_gateway import APIGatewayRestResolver +from aws_lambda_powertools.event_handler.openapi.models import ExternalDocumentation + + +def test_openapi_schema_no_external_documentation(): + app = APIGatewayRestResolver() + + schema = app.get_openapi_schema(title="Hello API", version="1.0.0") + assert not schema.externalDocs + + +def test_openapi_schema_external_documentation(): + app = APIGatewayRestResolver() + + schema = app.get_openapi_schema( + title="Hello API", + version="1.0.0", + external_documentation=ExternalDocumentation( + description="Find out more about this API", + url="https://example.org/docs", + ), + ) + + assert schema.externalDocs + assert schema.externalDocs.description == "Find out more about this API" + assert str(schema.externalDocs.url) == "https://example.org/docs"