Merge pull request 'add cors headers in exception handler in cors' (#506) from Mic92-sops-nix into main

This commit is contained in:
clan-bot
2023-11-14 15:42:46 +00:00
4 changed files with 72 additions and 39 deletions

View File

@@ -1,47 +1,24 @@
import logging
import os
from enum import Enum
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.routing import APIRoute
from fastapi.staticfiles import StaticFiles
from ..errors import ClanError
from .assets import asset_path
from .error_handlers import clan_error_handler
from .routers import clan_modules, flake, health, machines, root, vms
from .settings import settings
from .tags import tags_metadata
# Logging setup
log = logging.getLogger(__name__)
class EnvType(Enum):
production = "production"
development = "development"
@staticmethod
def from_environment() -> "EnvType":
t = os.environ.get("CLAN_WEBUI_ENV", "production")
try:
return EnvType[t]
except KeyError:
log.warning(f"Invalid environment type: {t}, fallback to production")
return EnvType.production
def is_production(self) -> bool:
return self == EnvType.production
def is_development(self) -> bool:
return self == EnvType.development
def setup_app() -> FastAPI:
env = EnvType.from_environment()
app = FastAPI()
if env.is_development():
if settings.env.is_development():
# Allow CORS in development mode for nextjs dev server
app.add_middleware(
CORSMiddleware,
@@ -59,7 +36,7 @@ def setup_app() -> FastAPI:
# Needs to be last in register. Because of wildcard route
app.include_router(root.router)
app.add_exception_handler(ClanError, clan_error_handler)
app.add_exception_handler(Exception, clan_error_handler)
app.mount("/static", StaticFiles(directory=asset_path()), name="static")

View File

@@ -5,20 +5,44 @@ from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
from ..errors import ClanError
from .settings import settings
log = logging.getLogger(__name__)
def clan_error_handler(request: Request, exc: Exception) -> JSONResponse:
assert isinstance(exc, ClanError)
log.error("ClanError: %s", exc)
detail = [
{
"loc": [],
"msg": str(exc),
}
]
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
content=jsonable_encoder(dict(detail=detail)),
)
headers = {}
if settings.env.is_development():
headers["Access-Control-Allow-Origin"] = "*"
headers["Access-Control-Allow-Methods"] = "*"
if isinstance(exc, ClanError):
log.error(f"ClanError: {exc}")
detail = [
{
"loc": [],
"msg": str(exc),
}
]
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
content=jsonable_encoder(dict(detail=detail)),
headers=headers,
)
else:
log.exception(f"Unhandled Exception: {exc}")
return JSONResponse(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
content=jsonable_encoder(
dict(
detail=[
{
"loc": [],
"msg": str(exc),
}
]
)
),
headers=headers,
)

View File

@@ -0,0 +1,32 @@
import logging
import os
from enum import Enum
log = logging.getLogger(__name__)
class EnvType(Enum):
production = "production"
development = "development"
@staticmethod
def from_environment() -> "EnvType":
t = os.environ.get("CLAN_WEBUI_ENV", "production")
try:
return EnvType[t]
except KeyError:
log.warning(f"Invalid environment type: {t}, fallback to production")
return EnvType.production
def is_production(self) -> bool:
return self == EnvType.production
def is_development(self) -> bool:
return self == EnvType.development
class Settings:
env = EnvType.from_environment()
settings = Settings()

View File

@@ -11,4 +11,4 @@ from clan_cli.webui.app import app
def api() -> TestClient:
# logging.getLogger("httpx").setLevel(level=logging.WARNING)
logging.getLogger("asyncio").setLevel(logging.INFO)
return TestClient(app)
return TestClient(app, raise_server_exceptions=False)