feat(realestate): 내부 인증 + naver 워커 targets 엔드포인트 + nginx internal 블록
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EqCYBhvTcdeCTUDX3RhWx9
This commit is contained in:
11
realestate-lab/app/auth.py
Normal file
11
realestate-lab/app/auth.py
Normal file
@@ -0,0 +1,11 @@
|
||||
"""Windows naver-fetch 워커 → NAS realestate-lab 내부 엔드포인트 인증."""
|
||||
import os
|
||||
from fastapi import Header, HTTPException
|
||||
|
||||
|
||||
def verify_internal_key(x_internal_key: str = Header(...)):
|
||||
expected = os.getenv("INTERNAL_API_KEY")
|
||||
if not expected:
|
||||
raise HTTPException(401, "INTERNAL_API_KEY not configured on server")
|
||||
if x_internal_key != expected:
|
||||
raise HTTPException(401, "Invalid X-Internal-Key")
|
||||
27
realestate-lab/app/internal_router.py
Normal file
27
realestate-lab/app/internal_router.py
Normal file
@@ -0,0 +1,27 @@
|
||||
"""naver-fetch 워커 내부 계약: targets 조회 + listings ingest."""
|
||||
import os
|
||||
import logging
|
||||
from fastapi import APIRouter, Depends
|
||||
|
||||
from .auth import verify_internal_key
|
||||
from .db import get_listing_criteria
|
||||
from .lawd_codes import naver_cortar
|
||||
|
||||
logger = logging.getLogger("realestate-lab")
|
||||
router = APIRouter()
|
||||
|
||||
NAVER_PAGE_LIMIT = int(os.getenv("NAVER_PAGE_LIMIT", "2"))
|
||||
|
||||
|
||||
@router.get("/api/internal/realestate/targets", dependencies=[Depends(verify_internal_key)])
|
||||
def listing_targets():
|
||||
crit = get_listing_criteria()
|
||||
dongs = []
|
||||
for d in crit.get("dongs", []):
|
||||
code = naver_cortar(d)
|
||||
if not code:
|
||||
logger.warning("naver cortarNo 매핑 없음 — 대상 제외: %s", d)
|
||||
continue
|
||||
dongs.append({"dong": d, "cortar_no": code})
|
||||
return {"dongs": dongs, "deal_types": crit.get("deal_types", []),
|
||||
"page_limit": NAVER_PAGE_LIMIT}
|
||||
@@ -29,6 +29,7 @@ from .models import (
|
||||
AnnouncementCreate, AnnouncementUpdate, ProfileUpdate,
|
||||
ListingCriteriaUpdate, SafetyCheckRequest, BudgetRequest,
|
||||
)
|
||||
from .internal_router import router as internal_router
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(name)s] %(levelname)s %(message)s")
|
||||
logger = logging.getLogger("realestate-lab")
|
||||
@@ -96,6 +97,7 @@ async def lifespan(app: FastAPI):
|
||||
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
install_access_log(app)
|
||||
app.include_router(internal_router)
|
||||
|
||||
_cors_origins = os.getenv("CORS_ALLOW_ORIGINS", "http://localhost:3007,http://localhost:8080").split(",")
|
||||
app.add_middleware(
|
||||
|
||||
Reference in New Issue
Block a user