diff --git a/docs/de/docs/how-to/custom-docs-ui-assets.md b/docs/de/docs/how-to/custom-docs-ui-assets.md index 6b8b1a176..574168079 100644 --- a/docs/de/docs/how-to/custom-docs-ui-assets.md +++ b/docs/de/docs/how-to/custom-docs-ui-assets.md @@ -34,7 +34,7 @@ Sie können die internen Funktionen von FastAPI wiederverwenden, um die HTML-Sei Und ähnlich für ReDoc ... -{* ../../docs_src/custom_docs_ui/tutorial001.py hl[2:6,11:19,22:24,27:33] *} +{* ../../docs_src/custom_docs_ui/tutorial001.py hl[2:6,11:20,23:25,28:35] *} /// tip | Tipp @@ -50,7 +50,7 @@ Swagger UI erledigt das hinter den Kulissen für Sie, benötigt aber diesen „U Um nun testen zu können, ob alles funktioniert, erstellen Sie eine *Pfadoperation*: -{* ../../docs_src/custom_docs_ui/tutorial001.py hl[36:38] *} +{* ../../docs_src/custom_docs_ui/tutorial001.py hl[38:40] *} ### Es testen { #test-it } @@ -160,7 +160,7 @@ Auch hier können Sie die internen Funktionen von FastAPI wiederverwenden, um di Und ähnlich für ReDoc ... -{* ../../docs_src/custom_docs_ui/tutorial002.py hl[2:6,14:22,25:27,30:36] *} +{* ../../docs_src/custom_docs_ui/tutorial002.py hl[2:6,14:23,26:28,31:38] *} /// tip | Tipp @@ -176,7 +176,7 @@ Swagger UI erledigt das hinter den Kulissen für Sie, benötigt aber diesen „U Um nun testen zu können, ob alles funktioniert, erstellen Sie eine *Pfadoperation*: -{* ../../docs_src/custom_docs_ui/tutorial002.py hl[39:41] *} +{* ../../docs_src/custom_docs_ui/tutorial002.py hl[41:43] *} ### Benutzeroberfläche mit statischen Dateien testen { #test-static-files-ui } diff --git a/docs/en/docs/how-to/custom-docs-ui-assets.md b/docs/en/docs/how-to/custom-docs-ui-assets.md index 91228c8c9..154b9b6c2 100644 --- a/docs/en/docs/how-to/custom-docs-ui-assets.md +++ b/docs/en/docs/how-to/custom-docs-ui-assets.md @@ -34,7 +34,7 @@ You can reuse FastAPI's internal functions to create the HTML pages for the docs And similarly for ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial001.py hl[2:6,11:19,22:24,27:33] *} +{* ../../docs_src/custom_docs_ui/tutorial001.py hl[2:6,11:20,23:25,28:35] *} /// tip @@ -50,7 +50,7 @@ Swagger UI will handle it behind the scenes for you, but it needs this "redirect Now, to be able to test that everything works, create a *path operation*: -{* ../../docs_src/custom_docs_ui/tutorial001.py hl[36:38] *} +{* ../../docs_src/custom_docs_ui/tutorial001.py hl[38:40] *} ### Test it { #test-it } @@ -160,7 +160,7 @@ Again, you can reuse FastAPI's internal functions to create the HTML pages for t And similarly for ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial002.py hl[2:6,14:22,25:27,30:36] *} +{* ../../docs_src/custom_docs_ui/tutorial002.py hl[2:6,14:23,26:28,31:38] *} /// tip @@ -176,7 +176,7 @@ Swagger UI will handle it behind the scenes for you, but it needs this "redirect Now, to be able to test that everything works, create a *path operation*: -{* ../../docs_src/custom_docs_ui/tutorial002.py hl[39:41] *} +{* ../../docs_src/custom_docs_ui/tutorial002.py hl[41:43] *} ### Test Static Files UI { #test-static-files-ui } diff --git a/docs/es/docs/how-to/custom-docs-ui-assets.md b/docs/es/docs/how-to/custom-docs-ui-assets.md index e9f977026..bc85ce1ac 100644 --- a/docs/es/docs/how-to/custom-docs-ui-assets.md +++ b/docs/es/docs/how-to/custom-docs-ui-assets.md @@ -34,7 +34,7 @@ Puedes reutilizar las funciones internas de FastAPI para crear las páginas HTML Y de manera similar para ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial001.py hl[2:6,11:19,22:24,27:33] *} +{* ../../docs_src/custom_docs_ui/tutorial001.py hl[2:6,11:20,23:25,28:35] *} /// tip | Consejo @@ -50,7 +50,7 @@ Swagger UI lo manejará detrás de escena para ti, pero necesita este auxiliar d Ahora, para poder probar que todo funciona, crea una *path operation*: -{* ../../docs_src/custom_docs_ui/tutorial001.py hl[36:38] *} +{* ../../docs_src/custom_docs_ui/tutorial001.py hl[38:40] *} ### Pruébalo { #test-it } @@ -160,7 +160,7 @@ Nuevamente, puedes reutilizar las funciones internas de FastAPI para crear las p Y de manera similar para ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial002.py hl[2:6,14:22,25:27,30:36] *} +{* ../../docs_src/custom_docs_ui/tutorial002.py hl[2:6,14:23,26:28,31:38] *} /// tip | Consejo @@ -176,7 +176,7 @@ Swagger UI lo manejará detrás de escena para ti, pero necesita este auxiliar d Ahora, para poder probar que todo funciona, crea una *path operation*: -{* ../../docs_src/custom_docs_ui/tutorial002.py hl[39:41] *} +{* ../../docs_src/custom_docs_ui/tutorial002.py hl[41:43] *} ### Prueba la UI de Archivos Estáticos { #test-static-files-ui } diff --git a/docs/pt/docs/how-to/custom-docs-ui-assets.md b/docs/pt/docs/how-to/custom-docs-ui-assets.md index 30224c72b..40f0c1b0a 100644 --- a/docs/pt/docs/how-to/custom-docs-ui-assets.md +++ b/docs/pt/docs/how-to/custom-docs-ui-assets.md @@ -34,7 +34,7 @@ Você pode reutilizar as funções internas do FastAPI para criar as páginas HT E de forma semelhante para o ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial001.py hl[2:6,11:19,22:24,27:33] *} +{* ../../docs_src/custom_docs_ui/tutorial001.py hl[2:6,11:20,23:25,28:35] *} /// tip | Dica @@ -50,7 +50,7 @@ Swagger UI lidará com isso nos bastidores para você, mas ele precisa desse aux Agora, para poder testar se tudo funciona, crie uma *operação de rota*: -{* ../../docs_src/custom_docs_ui/tutorial001.py hl[36:38] *} +{* ../../docs_src/custom_docs_ui/tutorial001.py hl[38:40] *} ### Teste { #test-it } @@ -160,7 +160,7 @@ Novamente, você pode reutilizar as funções internas do FastAPI para criar as E de forma semelhante para o ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial002.py hl[2:6,14:22,25:27,30:36] *} +{* ../../docs_src/custom_docs_ui/tutorial002.py hl[2:6,14:23,26:28,31:38] *} /// tip | Dica @@ -176,7 +176,7 @@ Swagger UI lidará com isso nos bastidores para você, mas ele precisa desse aux Agora, para poder testar se tudo funciona, crie uma *operação de rota*: -{* ../../docs_src/custom_docs_ui/tutorial002.py hl[39:41] *} +{* ../../docs_src/custom_docs_ui/tutorial002.py hl[41:43] *} ### Teste a UI de Arquivos Estáticos { #test-static-files-ui } diff --git a/docs/ru/docs/how-to/custom-docs-ui-assets.md b/docs/ru/docs/how-to/custom-docs-ui-assets.md index c07a9695b..aa82d5421 100644 --- a/docs/ru/docs/how-to/custom-docs-ui-assets.md +++ b/docs/ru/docs/how-to/custom-docs-ui-assets.md @@ -34,7 +34,7 @@ Аналогично и для ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial001.py hl[2:6,11:19,22:24,27:33] *} +{* ../../docs_src/custom_docs_ui/tutorial001.py hl[2:6,11:20,23:25,28:35] *} /// tip | Совет @@ -50,7 +50,7 @@ Swagger UI сделает это за вас «за кулисами», но д Чтобы убедиться, что всё работает, создайте *операцию пути*: -{* ../../docs_src/custom_docs_ui/tutorial001.py hl[36:38] *} +{* ../../docs_src/custom_docs_ui/tutorial001.py hl[38:40] *} ### Тестирование { #test-it } @@ -160,7 +160,7 @@ Swagger UI сделает это за вас «за кулисами», но д Аналогично и для ReDoc... -{* ../../docs_src/custom_docs_ui/tutorial002.py hl[2:6,14:22,25:27,30:36] *} +{* ../../docs_src/custom_docs_ui/tutorial002.py hl[2:6,14:23,26:28,31:38] *} /// tip | Совет @@ -176,7 +176,7 @@ Swagger UI сделает это за вас «за кулисами», но д Чтобы убедиться, что всё работает, создайте *операцию пути*: -{* ../../docs_src/custom_docs_ui/tutorial002.py hl[39:41] *} +{* ../../docs_src/custom_docs_ui/tutorial002.py hl[41:43] *} ### Тестирование UI со статическими файлами { #test-static-files-ui } diff --git a/docs_src/custom_docs_ui/tutorial001.py b/docs_src/custom_docs_ui/tutorial001.py index 1cfcce19a..776256dc5 100644 --- a/docs_src/custom_docs_ui/tutorial001.py +++ b/docs_src/custom_docs_ui/tutorial001.py @@ -1,4 +1,4 @@ -from fastapi import FastAPI +from fastapi import FastAPI, Request from fastapi.openapi.docs import ( get_redoc_html, get_swagger_ui_html, @@ -9,11 +9,12 @@ app = FastAPI(docs_url=None, redoc_url=None) @app.get("/docs", include_in_schema=False) -async def custom_swagger_ui_html(): +async def custom_swagger_ui_html(req: Request): + root_path = req.scope.get("root_path", "").rstrip("/") return get_swagger_ui_html( - openapi_url=app.openapi_url, + openapi_url=f"{root_path}{app.openapi_url}", title=app.title + " - Swagger UI", - oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url, + oauth2_redirect_url=f"{root_path}{app.swagger_ui_oauth2_redirect_url}", swagger_js_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js", swagger_css_url="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css", ) @@ -25,9 +26,10 @@ async def swagger_ui_redirect(): @app.get("/redoc", include_in_schema=False) -async def redoc_html(): +async def redoc_html(req: Request): + root_path = req.scope.get("root_path", "").rstrip("/") return get_redoc_html( - openapi_url=app.openapi_url, + openapi_url=f"{root_path}{app.openapi_url}", title=app.title + " - ReDoc", redoc_js_url="https://unpkg.com/redoc@2/bundles/redoc.standalone.js", ) diff --git a/docs_src/custom_docs_ui/tutorial002.py b/docs_src/custom_docs_ui/tutorial002.py index 23ea368f8..b2b61204d 100644 --- a/docs_src/custom_docs_ui/tutorial002.py +++ b/docs_src/custom_docs_ui/tutorial002.py @@ -1,4 +1,4 @@ -from fastapi import FastAPI +from fastapi import FastAPI, Request from fastapi.openapi.docs import ( get_redoc_html, get_swagger_ui_html, @@ -12,13 +12,14 @@ app.mount("/static", StaticFiles(directory="static"), name="static") @app.get("/docs", include_in_schema=False) -async def custom_swagger_ui_html(): +async def custom_swagger_ui_html(req: Request): + root_path = req.scope.get("root_path", "").rstrip("/") return get_swagger_ui_html( - openapi_url=app.openapi_url, + openapi_url=f"{root_path}{app.openapi_url}", title=app.title + " - Swagger UI", - oauth2_redirect_url=app.swagger_ui_oauth2_redirect_url, - swagger_js_url="/static/swagger-ui-bundle.js", - swagger_css_url="/static/swagger-ui.css", + oauth2_redirect_url=f"{root_path}{app.swagger_ui_oauth2_redirect_url}", + swagger_js_url=f"{root_path}/static/swagger-ui-bundle.js", + swagger_css_url=f"{root_path}/static/swagger-ui.css", ) @@ -28,11 +29,12 @@ async def swagger_ui_redirect(): @app.get("/redoc", include_in_schema=False) -async def redoc_html(): +async def redoc_html(req: Request): + root_path = req.scope.get("root_path", "").rstrip("/") return get_redoc_html( - openapi_url=app.openapi_url, + openapi_url=f"{root_path}{app.openapi_url}", title=app.title + " - ReDoc", - redoc_js_url="/static/redoc.standalone.js", + redoc_js_url=f"{root_path}/static/redoc.standalone.js", ) diff --git a/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py b/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py index cb8e8c224..4f40ba723 100644 --- a/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py +++ b/tests/test_tutorial/test_custom_docs_ui/test_tutorial001.py @@ -5,38 +5,61 @@ import pytest from fastapi.testclient import TestClient -@pytest.fixture(scope="module") -def client(): +@pytest.fixture( + params=["", "/api"], + ids=["Without path prefix", "With /api path prefix"], +) +def path_prefix(request: pytest.FixtureRequest): + return request.param + + +@pytest.fixture +def client(path_prefix: str): static_dir: Path = Path(os.getcwd()) / "static" print(static_dir) static_dir.mkdir(exist_ok=True) from docs_src.custom_docs_ui.tutorial001 import app - with TestClient(app) as client: + with TestClient(app, root_path=path_prefix, base_url="http://server") as client: yield client + static_dir.rmdir() -def test_swagger_ui_html(client: TestClient): - response = client.get("/docs") +def test_swagger_ui_html(client: TestClient, path_prefix: str): + response = client.get(f"{path_prefix}/docs") + assert response.request.url == f"http://server{path_prefix}/docs" assert response.status_code == 200, response.text assert "https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js" in response.text assert "https://unpkg.com/swagger-ui-dist@5/swagger-ui.css" in response.text + assert f"{path_prefix}/openapi.json" in response.text + assert f"{path_prefix}/docs/oauth2-redirect" in response.text -def test_swagger_ui_oauth2_redirect_html(client: TestClient): - response = client.get("/docs/oauth2-redirect") +def test_openapi_json(client: TestClient, path_prefix: str): + response = client.get(f"{path_prefix}/openapi.json") + assert response.request.url == f"http://server{path_prefix}/openapi.json" + assert response.status_code == 200, response.text + assert response.json()["openapi"] == "3.1.0" + + +def test_swagger_ui_oauth2_redirect_html(client: TestClient, path_prefix: str): + response = client.get(f"{path_prefix}/docs/oauth2-redirect") + assert response.request.url == f"http://server{path_prefix}/docs/oauth2-redirect" assert response.status_code == 200, response.text assert "window.opener.swaggerUIRedirectOauth2" in response.text -def test_redoc_html(client: TestClient): - response = client.get("/redoc") +def test_redoc_html(client: TestClient, path_prefix: str): + response = client.get(f"{path_prefix}/redoc") + assert response.request.url == f"http://server{path_prefix}/redoc" assert response.status_code == 200, response.text assert "https://unpkg.com/redoc@2/bundles/redoc.standalone.js" in response.text + assert f"{path_prefix}/openapi.json" in response.text -def test_api(client: TestClient): - response = client.get("/users/john") +def test_api(client: TestClient, path_prefix: str): + response = client.get(f"{path_prefix}/users/john") + assert response.request.url == f"http://server{path_prefix}/users/john" assert response.status_code == 200, response.text assert response.json()["message"] == "Hello john" diff --git a/tests/test_tutorial/test_custom_docs_ui/test_tutorial002.py b/tests/test_tutorial/test_custom_docs_ui/test_tutorial002.py index 712618807..3602f9125 100644 --- a/tests/test_tutorial/test_custom_docs_ui/test_tutorial002.py +++ b/tests/test_tutorial/test_custom_docs_ui/test_tutorial002.py @@ -5,38 +5,60 @@ import pytest from fastapi.testclient import TestClient -@pytest.fixture(scope="module") -def client(): +@pytest.fixture( + params=["", "/api"], + ids=["Without path prefix", "With /api path prefix"], +) +def path_prefix(request: pytest.FixtureRequest): + return request.param + + +@pytest.fixture +def client(path_prefix: str): static_dir: Path = Path(os.getcwd()) / "static" print(static_dir) static_dir.mkdir(exist_ok=True) from docs_src.custom_docs_ui.tutorial002 import app - with TestClient(app) as client: + with TestClient(app, root_path=path_prefix, base_url="http://server") as client: yield client + static_dir.rmdir() -def test_swagger_ui_html(client: TestClient): - response = client.get("/docs") +def test_swagger_ui_html(client: TestClient, path_prefix: str): + response = client.get(f"{path_prefix}/docs") + assert response.request.url == f"http://server{path_prefix}/docs" assert response.status_code == 200, response.text - assert "/static/swagger-ui-bundle.js" in response.text - assert "/static/swagger-ui.css" in response.text + assert f"{path_prefix}/static/swagger-ui-bundle.js" in response.text + assert f"{path_prefix}/static/swagger-ui.css" in response.text + assert f"{path_prefix}/docs/oauth2-redirect" in response.text -def test_swagger_ui_oauth2_redirect_html(client: TestClient): - response = client.get("/docs/oauth2-redirect") +def test_openapi_json(client: TestClient, path_prefix: str): + response = client.get(f"{path_prefix}/openapi.json") + assert response.request.url == f"http://server{path_prefix}/openapi.json" + assert response.status_code == 200, response.text + assert response.json()["openapi"] == "3.1.0" + + +def test_swagger_ui_oauth2_redirect_html(client: TestClient, path_prefix: str): + response = client.get(f"{path_prefix}/docs/oauth2-redirect") + assert response.request.url == f"http://server{path_prefix}/docs/oauth2-redirect" assert response.status_code == 200, response.text assert "window.opener.swaggerUIRedirectOauth2" in response.text -def test_redoc_html(client: TestClient): - response = client.get("/redoc") +def test_redoc_html(client: TestClient, path_prefix: str): + response = client.get(f"{path_prefix}/redoc") + assert response.request.url == f"http://server{path_prefix}/redoc" assert response.status_code == 200, response.text - assert "/static/redoc.standalone.js" in response.text + assert f"{path_prefix}/static/redoc.standalone.js" in response.text + assert f"{path_prefix}/openapi.json" in response.text -def test_api(client: TestClient): - response = client.get("/users/john") +def test_api(client: TestClient, path_prefix: str): + response = client.get(f"{path_prefix}/users/john") + assert response.request.url == f"http://server{path_prefix}/users/john" assert response.status_code == 200, response.text assert response.json()["message"] == "Hello john"