import time from contextlib import asynccontextmanager from fastapi import FastAPI, Request from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.gzip import GZipMiddleware from common.database.db_session_manager import DB_SESSION_MNG from common.logger import LOG from common.utils.gtime import GTime from config.server_configs import web_server_config import router.v1.auth.account import router.v1.negotiation.session import router.v1.chat.chat API_SERVER_START_TIME = GTime.UTCStr() @asynccontextmanager async def lifespan(app: FastAPI): # startup yield # shutdown: DB 엔진 커넥션 풀 정리 await DB_SESSION_MNG.dispose_all() app = FastAPI(title="Negosium Api Server", lifespan=lifespan) # CORS: config 의 cors_origins 가 있을 때만 적용(브라우저 프론트 호출 허용). # 명시적 오리진을 쓰므로 allow_credentials=True 가능(쿠키/Authorization 헤더 허용). if web_server_config.cors_origins: app.add_middleware( CORSMiddleware, allow_origins=web_server_config.cors_origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Accept-Encoding: gzip 요청에 대해 1000 bytes 이상 응답을 압축. app.add_middleware(GZipMiddleware, minimum_size=1000) @app.middleware("http") async def log_time(request: Request, call_next): start_time = time.time() response = await call_next(request) elapsed = time.time() - start_time LOG.d(f"took: {elapsed:.4f} - {request.url.path}") return response @app.get( path="/healthz", summary="헬스체크", description="서버 기동 시각(API_SERVER_START_TIME)을 반환하는 헬스체크 엔드포인트.", responses={404: {"description": "Not found"}}, ) async def healthz(): return API_SERVER_START_TIME # 각 도메인 라우터를 등록한다. 새 기능 추가 시 router.v1.. 를 import 후 include. app.include_router(router.v1.auth.account.router) app.include_router(router.v1.negotiation.session.router) app.include_router(router.v1.chat.chat.router)