From 2f3aa866613b3cbd5684ff0ea2c3ed427739cbe6 Mon Sep 17 00:00:00 2001 From: Carlos Mario Toro <41237977+cmtoro@users.noreply.github.com> Date: Tue, 13 May 2025 12:17:24 -0500 Subject: [PATCH 1/7] Add external_docs parameter to FastAPI class init external_docs is missing in FastAPI class. Added it to __init__ method to generate openapi spec --- fastapi/applications.py | 43 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/fastapi/applications.py b/fastapi/applications.py index 6d427cdc2..8e30cad22 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -810,6 +810,47 @@ class FastAPI(Starlette): """ ), ] = True, + external_docs: Annotated[ + Optional[Dict[str, Any]], + Doc( + """ + This field allows you to provide additional external documentation links + for an API operation or component. It’s an optional field and can be added + to an operation or a tag. If provided, it must be a dictionary containing: + + * `description`: A brief description of the external documentation, which may use + [CommonMark syntax](https://commonmark.org/) for rich text formatting. + * `url`: The URL pointing to the external documentation. The value **MUST** + be a valid URL format. + + **Example**: + + ```python + from fastapi import FastAPI + from typing import Dict, Any + from typing import Optional + from fastapi.openapi.models import Doc + from typing_extensions import Annotated + + external_docs: Annotated[Optional[Dict[str, Any]], Doc()] = { + "description": "Detailed API Reference", + "url": "https://example.com/api-docs", + } + + app = FastAPI(externalDocs=external_docs) + + ``` + + ### Explanation: + - `description`: Provides a short description explaining what this external documentation covers. + - `url`: Points to the full external documentation. + + **Notes**: + - This field is **optional**; if not included, no external documentation will be linked. + - You can use this feature to link to full API documentation, tutorials, or any other + """ + ), + ] = None, **extra: Annotated[ Any, Doc( @@ -838,6 +879,7 @@ class FastAPI(Starlette): self.swagger_ui_parameters = swagger_ui_parameters self.servers = servers or [] self.separate_input_output_schemas = separate_input_output_schemas + self.external_docs = external_docs self.extra = extra self.openapi_version: Annotated[ str, @@ -992,6 +1034,7 @@ class FastAPI(Starlette): tags=self.openapi_tags, servers=self.servers, separate_input_output_schemas=self.separate_input_output_schemas, + external_docs=self.external_docs, ) return self.openapi_schema From bb86eba0624072f4cb88de536f48fbec2dfc67a2 Mon Sep 17 00:00:00 2001 From: Carlos Mario Toro <41237977+cmtoro@users.noreply.github.com> Date: Tue, 13 May 2025 12:21:14 -0500 Subject: [PATCH 2/7] Add external_docs parameters to get_openapi method The OpenAPI class is being instantiated without the externalDocs parameter. --- fastapi/openapi/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index 808646cc2..b2913963e 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -489,6 +489,7 @@ def get_openapi( contact: Optional[Dict[str, Union[str, Any]]] = None, license_info: Optional[Dict[str, Union[str, Any]]] = None, separate_input_output_schemas: bool = True, + external_docs: Optional[Dict[str, Any]] = None, ) -> Dict[str, Any]: info: Dict[str, Any] = {"title": title, "version": version} if summary: @@ -566,4 +567,6 @@ def get_openapi( output["webhooks"] = webhook_paths if tags: output["tags"] = tags + if external_docs: + output["externalDocs"] = external_docs return jsonable_encoder(OpenAPI(**output), by_alias=True, exclude_none=True) # type: ignore From 1e7c36272986fae77b4e47f650cd7c6ffed83448 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 17:21:48 +0000 Subject: [PATCH 3/7] =?UTF-8?q?=F0=9F=8E=A8=20[pre-commit.ci]=20Auto=20for?= =?UTF-8?q?mat=20from=20pre-commit.com=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/applications.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastapi/applications.py b/fastapi/applications.py index 8e30cad22..fd2856321 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -838,7 +838,7 @@ class FastAPI(Starlette): } app = FastAPI(externalDocs=external_docs) - + ``` ### Explanation: From 7d7516879ab64e77939f73b5bbff886daf3433f2 Mon Sep 17 00:00:00 2001 From: Carlos Mario Toro <41237977+cmtoro@users.noreply.github.com> Date: Tue, 13 May 2025 13:54:39 -0500 Subject: [PATCH 4/7] Update test_openapi_examples.py --- tests/test_openapi_examples.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/test_openapi_examples.py b/tests/test_openapi_examples.py index b3f83ae23..77d275e97 100644 --- a/tests/test_openapi_examples.py +++ b/tests/test_openapi_examples.py @@ -5,7 +5,12 @@ from fastapi import Body, Cookie, FastAPI, Header, Path, Query from fastapi.testclient import TestClient from pydantic import BaseModel -app = FastAPI() +external_docs = { + "description": "External API documentation.", + "url": "https://docs.example.com/api-general" +} + +app = FastAPI(external_docs=external_docs) class Item(BaseModel): @@ -468,4 +473,8 @@ def test_openapi_schema(): }, } }, + "externalDocs": { + "description": "External API documentation.", + "url": "https://docs.example.com/api-general" + }, } From a28c2b7a21e637f63818f37a294ebd4b913a52fb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 18:54:49 +0000 Subject: [PATCH 5/7] =?UTF-8?q?=F0=9F=8E=A8=20[pre-commit.ci]=20Auto=20for?= =?UTF-8?q?mat=20from=20pre-commit.com=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_openapi_examples.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_openapi_examples.py b/tests/test_openapi_examples.py index 77d275e97..7c4518bd8 100644 --- a/tests/test_openapi_examples.py +++ b/tests/test_openapi_examples.py @@ -7,7 +7,7 @@ from pydantic import BaseModel external_docs = { "description": "External API documentation.", - "url": "https://docs.example.com/api-general" + "url": "https://docs.example.com/api-general", } app = FastAPI(external_docs=external_docs) @@ -475,6 +475,6 @@ def test_openapi_schema(): }, "externalDocs": { "description": "External API documentation.", - "url": "https://docs.example.com/api-general" + "url": "https://docs.example.com/api-general", }, } From 7001d1b53c991b1ff41ee54f13357071513c48b1 Mon Sep 17 00:00:00 2001 From: Carlos Mario Toro <41237977+cmtoro@users.noreply.github.com> Date: Wed, 14 May 2025 15:28:08 -0500 Subject: [PATCH 6/7] Update applications.py --- fastapi/applications.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fastapi/applications.py b/fastapi/applications.py index fd2856321..c139e7f3c 100644 --- a/fastapi/applications.py +++ b/fastapi/applications.py @@ -810,7 +810,7 @@ class FastAPI(Starlette): """ ), ] = True, - external_docs: Annotated[ + openapi_external_docs: Annotated[ Optional[Dict[str, Any]], Doc( """ @@ -837,7 +837,7 @@ class FastAPI(Starlette): "url": "https://example.com/api-docs", } - app = FastAPI(externalDocs=external_docs) + app = FastAPI(openapi_external_docs=external_docs) ``` @@ -879,7 +879,7 @@ class FastAPI(Starlette): self.swagger_ui_parameters = swagger_ui_parameters self.servers = servers or [] self.separate_input_output_schemas = separate_input_output_schemas - self.external_docs = external_docs + self.openapi_external_docs = openapi_external_docs self.extra = extra self.openapi_version: Annotated[ str, @@ -1034,7 +1034,7 @@ class FastAPI(Starlette): tags=self.openapi_tags, servers=self.servers, separate_input_output_schemas=self.separate_input_output_schemas, - external_docs=self.external_docs, + external_docs=self.openapi_external_docs, ) return self.openapi_schema From e6836b44936006a93fd1e3f32d4e36709adb64e0 Mon Sep 17 00:00:00 2001 From: Carlos Mario Toro <41237977+cmtoro@users.noreply.github.com> Date: Wed, 14 May 2025 15:29:04 -0500 Subject: [PATCH 7/7] Update test_openapi_examples.py --- tests/test_openapi_examples.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_openapi_examples.py b/tests/test_openapi_examples.py index 7c4518bd8..85b74aa43 100644 --- a/tests/test_openapi_examples.py +++ b/tests/test_openapi_examples.py @@ -10,7 +10,7 @@ external_docs = { "url": "https://docs.example.com/api-general", } -app = FastAPI(external_docs=external_docs) +app = FastAPI(openapi_external_docs=external_docs) class Item(BaseModel):