Skip to content

Commit 318036f

Browse files
mhinderyMathieu Hinderyckxleandrodamascena
authored
feat(event_handler): add support for externalDocs attribute in OpenAPI schema (#6945)
* Add top-level externalDocs support * add formal test * cleanup import * Update aws_lambda_powertools/event_handler/api_gateway.py Co-authored-by: Leandro Damascena <[email protected]> Signed-off-by: Mathieu Hinderyckx <[email protected]> * Fix test --------- Signed-off-by: Mathieu Hinderyckx <[email protected]> Co-authored-by: Mathieu Hinderyckx <[email protected]> Co-authored-by: Leandro Damascena <[email protected]>
1 parent eaedf5e commit 318036f

File tree

3 files changed

+52
-0
lines changed

3 files changed

+52
-0
lines changed

aws_lambda_powertools/event_handler/api_gateway.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
)
8686
from aws_lambda_powertools.event_handler.openapi.models import (
8787
Contact,
88+
ExternalDocumentation,
8889
License,
8990
OpenAPI,
9091
SecurityScheme,
@@ -1714,6 +1715,7 @@ def get_openapi_schema(
17141715
license_info: License | None = None,
17151716
security_schemes: dict[str, SecurityScheme] | None = None,
17161717
security: list[dict[str, list[str]]] | None = None,
1718+
external_documentation: ExternalDocumentation | None = None,
17171719
openapi_extensions: dict[str, Any] | None = None,
17181720
) -> OpenAPI:
17191721
"""
@@ -1745,6 +1747,8 @@ def get_openapi_schema(
17451747
A declaration of the security schemes available to be used in the specification.
17461748
security: list[dict[str, list[str]]], optional
17471749
A declaration of which security mechanisms are applied globally across the API.
1750+
external_documentation: ExternalDocumentation, optional
1751+
Additional external documentation for the API.
17481752
openapi_extensions: Dict[str, Any], optional
17491753
Additional OpenAPI extensions as a dictionary.
17501754
@@ -1775,6 +1779,7 @@ def get_openapi_schema(
17751779
license_info = license_info or self.openapi_config.license_info
17761780
security_schemes = security_schemes or self.openapi_config.security_schemes
17771781
security = security or self.openapi_config.security
1782+
external_documentation = external_documentation or self.openapi_config.external_documentation
17781783
openapi_extensions = openapi_extensions or self.openapi_config.openapi_extensions
17791784

17801785
from pydantic.json_schema import GenerateJsonSchema
@@ -1814,6 +1819,9 @@ def get_openapi_schema(
18141819
**openapi_extensions,
18151820
}
18161821

1822+
if external_documentation:
1823+
output["externalDocs"] = external_documentation
1824+
18171825
components: dict[str, dict[str, Any]] = {}
18181826
paths: dict[str, dict[str, Any]] = {}
18191827
operation_ids: set[str] = set()
@@ -1921,6 +1929,7 @@ def get_openapi_json_schema(
19211929
license_info: License | None = None,
19221930
security_schemes: dict[str, SecurityScheme] | None = None,
19231931
security: list[dict[str, list[str]]] | None = None,
1932+
external_documentation: ExternalDocumentation | None = None,
19241933
openapi_extensions: dict[str, Any] | None = None,
19251934
) -> str:
19261935
"""
@@ -1952,6 +1961,8 @@ def get_openapi_json_schema(
19521961
A declaration of the security schemes available to be used in the specification.
19531962
security: list[dict[str, list[str]]], optional
19541963
A declaration of which security mechanisms are applied globally across the API.
1964+
external_documentation: ExternalDocumentation, optional
1965+
Additional external documentation for the API.
19551966
openapi_extensions: Dict[str, Any], optional
19561967
Additional OpenAPI extensions as a dictionary.
19571968
@@ -1977,6 +1988,7 @@ def get_openapi_json_schema(
19771988
license_info=license_info,
19781989
security_schemes=security_schemes,
19791990
security=security,
1991+
external_documentation=external_documentation,
19801992
openapi_extensions=openapi_extensions,
19811993
),
19821994
by_alias=True,
@@ -1998,6 +2010,7 @@ def configure_openapi(
19982010
license_info: License | None = None,
19992011
security_schemes: dict[str, SecurityScheme] | None = None,
20002012
security: list[dict[str, list[str]]] | None = None,
2013+
external_documentation: ExternalDocumentation | None = None,
20012014
openapi_extensions: dict[str, Any] | None = None,
20022015
):
20032016
"""Configure OpenAPI specification settings for the API.
@@ -2031,6 +2044,8 @@ def configure_openapi(
20312044
A declaration of the security schemes available to be used in the specification.
20322045
security: list[dict[str, list[str]]], optional
20332046
A declaration of which security mechanisms are applied globally across the API.
2047+
external_documentation: ExternalDocumentation, optional
2048+
A link to external documentation for the API.
20342049
openapi_extensions: Dict[str, Any], optional
20352050
Additional OpenAPI extensions as a dictionary.
20362051
@@ -2064,6 +2079,7 @@ def configure_openapi(
20642079
license_info=license_info,
20652080
security_schemes=security_schemes,
20662081
security=security,
2082+
external_documentation=external_documentation,
20672083
openapi_extensions=openapi_extensions,
20682084
)
20692085

@@ -2088,6 +2104,7 @@ def enable_swagger(
20882104
security: list[dict[str, list[str]]] | None = None,
20892105
oauth2_config: OAuth2Config | None = None,
20902106
persist_authorization: bool = False,
2107+
external_documentation: ExternalDocumentation | None = None,
20912108
openapi_extensions: dict[str, Any] | None = None,
20922109
):
20932110
"""
@@ -2131,6 +2148,8 @@ def enable_swagger(
21312148
The OAuth2 configuration for the Swagger UI.
21322149
persist_authorization: bool, optional
21332150
Whether to persist authorization data on browser close/refresh.
2151+
external_documentation: ExternalDocumentation, optional
2152+
A link to external documentation for the API.
21342153
openapi_extensions: dict[str, Any], optional
21352154
Additional OpenAPI extensions as a dictionary.
21362155
"""
@@ -2183,6 +2202,7 @@ def swagger_handler():
21832202
license_info=license_info,
21842203
security_schemes=security_schemes,
21852204
security=security,
2205+
external_documentation=external_documentation,
21862206
openapi_extensions=openapi_extensions,
21872207
)
21882208

aws_lambda_powertools/event_handler/openapi/config.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
if TYPE_CHECKING:
1313
from aws_lambda_powertools.event_handler.openapi.models import (
1414
Contact,
15+
ExternalDocumentation,
1516
License,
1617
SecurityScheme,
1718
Server,
@@ -51,6 +52,8 @@ class OpenAPIConfig:
5152
A declaration of the security schemes available to be used in the specification.
5253
security: list[dict[str, list[str]]], optional
5354
A declaration of which security mechanisms are applied globally across the API.
55+
external_documentation: ExternalDocumentation, optional
56+
A link to external documentation for the API.
5457
openapi_extensions: Dict[str, Any], optional
5558
Additional OpenAPI extensions as a dictionary.
5659
@@ -77,4 +80,5 @@ class OpenAPIConfig:
7780
license_info: License | None = None
7881
security_schemes: dict[str, SecurityScheme] | None = None
7982
security: list[dict[str, list[str]]] | None = None
83+
external_documentation: ExternalDocumentation | None = None
8084
openapi_extensions: dict[str, Any] | None = None
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from __future__ import annotations
2+
3+
from aws_lambda_powertools.event_handler.api_gateway import APIGatewayRestResolver
4+
from aws_lambda_powertools.event_handler.openapi.models import ExternalDocumentation
5+
6+
7+
def test_openapi_schema_no_external_documentation():
8+
app = APIGatewayRestResolver()
9+
10+
schema = app.get_openapi_schema(title="Hello API", version="1.0.0")
11+
assert not schema.externalDocs
12+
13+
14+
def test_openapi_schema_external_documentation():
15+
app = APIGatewayRestResolver()
16+
17+
schema = app.get_openapi_schema(
18+
title="Hello API",
19+
version="1.0.0",
20+
external_documentation=ExternalDocumentation(
21+
description="Find out more about this API",
22+
url="https://example.org/docs",
23+
),
24+
)
25+
26+
assert schema.externalDocs
27+
assert schema.externalDocs.description == "Find out more about this API"
28+
assert str(schema.externalDocs.url) == "https://example.org/docs"

0 commit comments

Comments
 (0)