caainp-backend / core /cookie.py
windopper
remove nav_bridge.py and update dependencies in pyproject.toml and README.md to reflect changes in navigation API endpoints and session management
7bee6d4
from fastapi import Request, Response
from caainp_csm.plan_csm import PlanState, Constraints, Step
import json
COOKIE_KEY = "CAAINP-NAVIGATION-COOKIE"
def plan_to_dict(plan: PlanState) -> dict:
"""PlanState를 JSON 직렬화 가능한 dict로 변환"""
return {
"constraints": {
"use_elevator_only": plan.constraints.use_elevator_only,
"avoid_stairs": plan.constraints.avoid_stairs,
"forbidden_nodes": plan.constraints.forbidden_nodes,
"via_rooms": plan.constraints.via_rooms,
},
"steps": [
{
"step_id": s.step_id,
"goal_type": s.goal_type,
"goal_room": s.goal_room,
"allowed_moves": s.allowed_moves,
"description_ko": s.description_ko,
"target_nodes": s.target_nodes,
"route_nodes": s.route_nodes,
}
for s in plan.steps
],
"current_step": plan.current_step,
"steps_status": plan.steps_status,
"step_targets": {str(k): v for k, v in plan.step_targets.items()},
"in_target_count": plan.in_target_count,
}
def dict_to_plan(data: dict) -> PlanState:
"""dict를 PlanState 객체로 복원"""
constraints = Constraints(
use_elevator_only=data["constraints"]["use_elevator_only"],
avoid_stairs=data["constraints"]["avoid_stairs"],
forbidden_nodes=data["constraints"]["forbidden_nodes"],
via_rooms=data["constraints"]["via_rooms"],
)
steps = [
Step(
step_id=s["step_id"],
goal_type=s["goal_type"],
goal_room=s["goal_room"],
allowed_moves=s["allowed_moves"],
description_ko=s["description_ko"],
target_nodes=s["target_nodes"],
route_nodes=s["route_nodes"],
)
for s in data["steps"]
]
# steps_status의 키를 int로 복원
steps_status = {int(k): v for k, v in data["steps_status"].items()}
# step_targets의 키를 int로 복원
step_targets = {int(k): v for k, v in data["step_targets"].items()}
return PlanState(
constraints=constraints,
steps=steps,
current_step=data["current_step"],
steps_status=steps_status,
step_targets=step_targets,
in_target_count=data["in_target_count"],
)
def get_nav_state_from_cookie(request: Request) -> tuple[PlanState, int] | None:
"""쿠키에서 네비게이션 상태를 읽어서 반환"""
cookies = dict(request.cookies)
nav_state_cookie = cookies.get(COOKIE_KEY)
if not nav_state_cookie:
return None
try:
nav_state = json.loads(nav_state_cookie)
plan_dict = nav_state.get("plan")
prev_node = nav_state.get("prev_node")
plan = dict_to_plan(plan_dict)
return plan, prev_node
except (json.JSONDecodeError, KeyError, TypeError):
return None
def save_nav_state_to_cookie(response: Response, plan: PlanState, prev_node: int) -> None:
"""네비게이션 상태(plan, prev_node)를 쿠키에 저장"""
nav_state = {
"plan": plan_to_dict(plan),
"prev_node": prev_node,
}
response.set_cookie(
key=COOKIE_KEY,
value=json.dumps(nav_state),
max_age=3600,
httponly=True,
samesite="lax"
)
def clear_nav_cookie(response: Response) -> None:
"""네비게이션 쿠키 삭제"""
response.delete_cookie(COOKIE_KEY)