| @@ -1,8 +1,10 @@ | |||
| import asyncio | |||
| import json | |||
| from fastapi import APIRouter, Depends, HTTPException, Query, Request | |||
| import httpx | |||
| import config_env | |||
| from typing import List, Optional | |||
| from urllib.parse import urlencode | |||
| from schemas.reslevis import ( | |||
| BuildingItem, | |||
| @@ -170,12 +172,42 @@ async def _core_get_json( | |||
| raise HTTPException(status_code=502, detail="Invalid CORE response") from exc | |||
| async def _core_get_json_via_curl( | |||
| path: str, | |||
| params: Optional[dict] = None, | |||
| ): | |||
| query_string = urlencode(params or {}) | |||
| url = f"{CORE_BASE_URL}{path}" | |||
| if query_string: | |||
| url = f"{url}?{query_string}" | |||
| cmd = ["curl", "-sS", "-X", "GET"] | |||
| if CORE_BASE_URL.startswith("https://"): | |||
| cmd.append("-k") | |||
| cmd.append(url) | |||
| process = await asyncio.create_subprocess_exec( | |||
| *cmd, | |||
| stdout=asyncio.subprocess.PIPE, | |||
| stderr=asyncio.subprocess.PIPE, | |||
| ) | |||
| stdout, stderr = await process.communicate() | |||
| if process.returncode != 0: | |||
| detail = (stderr or stdout).decode("utf-8", errors="replace").strip() or "CORE curl request failed" | |||
| raise HTTPException(status_code=502, detail=detail) | |||
| try: | |||
| return json.loads(stdout.decode("utf-8")) | |||
| except ValueError as exc: | |||
| raise HTTPException(status_code=502, detail="Invalid CORE response") from exc | |||
| async def _fetch_tracks_for_tracker( | |||
| client: httpx.AsyncClient, | |||
| tracker_id: str, | |||
| params: Optional[dict] = None, | |||
| ) -> List[dict]: | |||
| payload = await _core_get_json(client, f"/reslevis/getTracks/{tracker_id}", params=params) | |||
| payload = await _core_get_json_via_curl(f"/reslevis/getTracks/{tracker_id}", params=params) | |||
| if not isinstance(payload, list): | |||
| raise HTTPException(status_code=502, detail="Unexpected CORE response type") | |||
| return [_normalize_track(row) for row in payload if isinstance(row, dict)] | |||
| @@ -186,22 +218,21 @@ def _sort_tracks_desc(rows: List[dict]) -> List[dict]: | |||
| async def _fetch_all_tracks(params: dict) -> List[dict]: | |||
| async with httpx.AsyncClient(timeout=30.0, verify=False) as client: | |||
| trackers_payload = await _core_get_json(client, "/reslevis/getTrackers") | |||
| if not isinstance(trackers_payload, list): | |||
| raise HTTPException(status_code=502, detail="Unexpected CORE tracker response type") | |||
| tracker_ids = [] | |||
| for item in trackers_payload: | |||
| if not isinstance(item, dict): | |||
| continue | |||
| tracker_id = item.get("id") | |||
| if tracker_id: | |||
| tracker_ids.append(str(tracker_id)) | |||
| batches = await asyncio.gather( | |||
| *[_fetch_tracks_for_tracker(client, tracker_id, params) for tracker_id in tracker_ids] | |||
| ) | |||
| trackers_payload = await _core_get_json_via_curl("/reslevis/getTrackers") | |||
| if not isinstance(trackers_payload, list): | |||
| raise HTTPException(status_code=502, detail="Unexpected CORE tracker response type") | |||
| tracker_ids = [] | |||
| for item in trackers_payload: | |||
| if not isinstance(item, dict): | |||
| continue | |||
| tracker_id = item.get("id") | |||
| if tracker_id: | |||
| tracker_ids.append(str(tracker_id)) | |||
| batches = await asyncio.gather( | |||
| *[_fetch_tracks_for_tracker(tracker_id, params) for tracker_id in tracker_ids] | |||
| ) | |||
| merged = [row for batch in batches for row in batch] | |||
| merged = _sort_tracks_desc(merged) | |||
| @@ -402,13 +433,9 @@ async def getTracks( | |||
| selected_tracker_id = tracker_id or request.query_params.get("id") | |||
| try: | |||
| if selected_tracker_id: | |||
| async with httpx.AsyncClient(timeout=30.0, verify=False) as client: | |||
| return await _fetch_tracks_for_tracker(client, selected_tracker_id, params) | |||
| return await _fetch_all_tracks(params) | |||
| except httpx.RequestError as exc: | |||
| raise HTTPException(status_code=502, detail=f"CORE request failed: {exc}") from exc | |||
| if selected_tracker_id: | |||
| return await _fetch_tracks_for_tracker(selected_tracker_id, params) | |||
| return await _fetch_all_tracks(params) | |||
| @router.get( | |||
| @@ -431,11 +458,7 @@ async def getTrack( | |||
| if to: | |||
| params["to"] = to | |||
| try: | |||
| async with httpx.AsyncClient(timeout=30.0, verify=False) as client: | |||
| return await _fetch_tracks_for_tracker(client, tracker_id, params) | |||
| except httpx.RequestError as exc: | |||
| raise HTTPException(status_code=502, detail=f"CORE request failed: {exc}") from exc | |||
| return await _fetch_tracks_for_tracker(tracker_id, params) | |||
| @router.post("/postTrack", tags=["Reslevis"], dependencies=[Depends(get_current_user)]) | |||