diff --git a/test/e2e/__snapshots__/test_missing_core/test_missing_core_422.json b/test/e2e/__snapshots__/test_missing_core/test_missing_core_422.json new file mode 100644 index 000000000..e7f74b496 --- /dev/null +++ b/test/e2e/__snapshots__/test_missing_core/test_missing_core_422.json @@ -0,0 +1,3 @@ +{ + "message": "バージョン 4.0.4 のコアが見つかりません" +} diff --git a/test/e2e/test_missing_core.py b/test/e2e/test_missing_core.py new file mode 100644 index 000000000..39e241fa2 --- /dev/null +++ b/test/e2e/test_missing_core.py @@ -0,0 +1,11 @@ +"""コア取得失敗のテスト""" + +from fastapi.testclient import TestClient +from syrupy.assertion import SnapshotAssertion + + +def test_missing_core_422(client: TestClient, snapshot_json: SnapshotAssertion) -> None: + """存在しないコアを指定するとエラーを返す。""" + response = client.get("/supported_devices", params={"core_version": "4.0.4"}) + assert response.status_code == 422 + assert snapshot_json == response.json() diff --git a/test/test_core_initializer.py b/test/test_core_initializer.py index 6e8ff7056..954c5ac1e 100644 --- a/test/test_core_initializer.py +++ b/test/test_core_initializer.py @@ -3,10 +3,13 @@ from unittest.mock import patch import pytest -from fastapi import HTTPException from voicevox_engine.core.core_adapter import CoreAdapter -from voicevox_engine.core.core_initializer import CoreManager, get_half_logical_cores +from voicevox_engine.core.core_initializer import ( + CoreManager, + CoreNotFound, + get_half_logical_cores, +) from voicevox_engine.dev.core.mock import MockCoreWrapper @@ -93,7 +96,7 @@ def test_cores_get_core_missing() -> None: core_manager.register_core(core2, "0.0.2") # Test - with pytest.raises(HTTPException) as _: + with pytest.raises(CoreNotFound): core_manager.get_core("0.0.3") diff --git a/voicevox_engine/app/application.py b/voicevox_engine/app/application.py index bbe435f1d..d49c2d1b0 100644 --- a/voicevox_engine/app/application.py +++ b/voicevox_engine/app/application.py @@ -4,6 +4,7 @@ from voicevox_engine import __version__ from voicevox_engine.app.dependencies import deprecated_mutable_api +from voicevox_engine.app.global_exceptions import configure_global_exception_handlers from voicevox_engine.app.middlewares import configure_middlewares from voicevox_engine.app.openapi_schema import configure_openapi_schema from voicevox_engine.app.routers.engine_info import generate_engine_info_router @@ -51,6 +52,7 @@ def generate_app( version=__version__, ) app = configure_middlewares(app, cors_policy_mode, allow_origin) + app = configure_global_exception_handlers(app) if disable_mutable_api: deprecated_mutable_api.enable = False diff --git a/voicevox_engine/app/global_exceptions.py b/voicevox_engine/app/global_exceptions.py new file mode 100644 index 000000000..81a00bfd1 --- /dev/null +++ b/voicevox_engine/app/global_exceptions.py @@ -0,0 +1,17 @@ +"""グローバルな例外ハンドラの定義と登録""" + +from fastapi import FastAPI, Request +from fastapi.responses import JSONResponse + +from voicevox_engine.core.core_initializer import CoreNotFound + + +def configure_global_exception_handlers(app: FastAPI) -> FastAPI: + """グローバルな例外ハンドラを app へ設定する。""" + + # 指定されたコアが見つからないエラー + @app.exception_handler(CoreNotFound) + async def cnf_exception_handler(request: Request, e: CoreNotFound) -> JSONResponse: + return JSONResponse(status_code=422, content={"message": f"{str(e)}"}) + + return app diff --git a/voicevox_engine/core/core_initializer.py b/voicevox_engine/core/core_initializer.py index 14b3eef1d..b8a4bc5d1 100644 --- a/voicevox_engine/core/core_initializer.py +++ b/voicevox_engine/core/core_initializer.py @@ -3,8 +3,6 @@ import sys from pathlib import Path -from fastapi import HTTPException - from ..utility.core_version_utility import get_latest_version from ..utility.path_utility import engine_root, get_save_dir from .core_adapter import CoreAdapter @@ -20,6 +18,12 @@ def get_half_logical_cores() -> int: return logical_cores // 2 +class CoreNotFound(Exception): + """コアが見つからないエラー""" + + pass + + class CoreManager: """コアの集まりを一括管理するマネージャー""" @@ -44,9 +48,7 @@ def get_core(self, version: str | None = None) -> CoreAdapter: return self._cores[self.latest_version()] elif version in self._cores: return self._cores[version] - - # FIXME: ドメインがずれているのでこのエラーは routers へ持っていく - raise HTTPException(status_code=422, detail="不明なバージョンです") + raise CoreNotFound(f"バージョン {version} のコアが見つかりません") def has_core(self, version: str) -> bool: """指定バージョンのコアが登録されているか否かを返す。"""