This commit is contained in:
parent
d57548f273
commit
276647e079
@ -4,6 +4,7 @@ from __future__ import annotations
|
|||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
from typing import Any, Dict, Tuple
|
from typing import Any, Dict, Tuple
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -11,6 +12,9 @@ from django.http import JsonResponse, HttpRequest
|
|||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django.views.decorators.http import require_http_methods, require_POST
|
from django.views.decorators.http import require_http_methods, require_POST
|
||||||
|
|
||||||
|
# build absolute public URLs from a request + path
|
||||||
|
from core.urlbuild import public_url
|
||||||
|
|
||||||
# ----- contracts version (best-effort) -----
|
# ----- contracts version (best-effort) -----
|
||||||
try:
|
try:
|
||||||
from pxy_contracts.version import SPEC_VERSION
|
from pxy_contracts.version import SPEC_VERSION
|
||||||
@ -24,7 +28,7 @@ AGENTS_INTERNAL_BASE = getattr(settings, "AGENTS_INTERNAL_BASE", "")
|
|||||||
# For the formatter endpoints we *force* an internal base and never guess from Host.
|
# For the formatter endpoints we *force* an internal base and never guess from Host.
|
||||||
# Set in .env: AGENTS_INTERNAL_BASE=http://127.0.0.1:8002
|
# Set in .env: AGENTS_INTERNAL_BASE=http://127.0.0.1:8002
|
||||||
# Fallback keeps you safe even if env is missing/misread.
|
# Fallback keeps you safe even if env is missing/misread.
|
||||||
FORMAT_INTERNAL_BASE = AGENTS_INTERNAL_BASE or "http://127.0.0.1:8002"
|
FORMAT_INTERNAL_BASE = (AGENTS_INTERNAL_BASE or "http://127.0.0.1:8002").rstrip("/")
|
||||||
|
|
||||||
# ===== helpers =====
|
# ===== helpers =====
|
||||||
def _load_body(request: HttpRequest) -> Dict[str, Any]:
|
def _load_body(request: HttpRequest) -> Dict[str, Any]:
|
||||||
@ -59,7 +63,7 @@ def _post_underlying(agent: str, payload: Dict[str, Any], timeout: float = 60.0)
|
|||||||
sites -> /api/sites/search
|
sites -> /api/sites/search
|
||||||
"""
|
"""
|
||||||
path = "/api/sami/run" if agent == "sami" else "/api/sites/search"
|
path = "/api/sami/run" if agent == "sami" else "/api/sites/search"
|
||||||
url = f"{FORMAT_INTERNAL_BASE.rstrip('/')}{path}"
|
url = f"{FORMAT_INTERNAL_BASE}{path}"
|
||||||
try:
|
try:
|
||||||
r = requests.post(url, json=payload, timeout=timeout)
|
r = requests.post(url, json=payload, timeout=timeout)
|
||||||
try:
|
try:
|
||||||
@ -72,6 +76,37 @@ def _post_underlying(agent: str, payload: Dict[str, Any], timeout: float = 60.0)
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return 500, {"code": "EXEC_ERROR", "message": str(e), "_debug_url": url}
|
return 500, {"code": "EXEC_ERROR", "message": str(e), "_debug_url": url}
|
||||||
|
|
||||||
|
def _normalize_urls_to_public(data: dict, request: HttpRequest) -> None:
|
||||||
|
"""
|
||||||
|
Convert any absolute URLs that may point to 127.0.0.1:8002 into public URLs
|
||||||
|
using the current request host while preserving the path.
|
||||||
|
"""
|
||||||
|
if not isinstance(data, dict):
|
||||||
|
return
|
||||||
|
|
||||||
|
url_keys = {
|
||||||
|
# common keys from sami + sites
|
||||||
|
"share_url", "map_url", "demand_map_url", "competition_map_url",
|
||||||
|
"main_download_url", "demand_download_url", "competition_download_url",
|
||||||
|
"main_preview_url", "demand_preview_url", "competition_preview_url",
|
||||||
|
"isochrones_geojson_url", "candidates_geojson_url",
|
||||||
|
"pois_competition_geojson_url", "popgrid_geojson_url",
|
||||||
|
"chart_url",
|
||||||
|
}
|
||||||
|
|
||||||
|
for k in list(url_keys):
|
||||||
|
v = data.get(k)
|
||||||
|
if not isinstance(v, str) or not v:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
p = urlparse(v)
|
||||||
|
# only rewrite absolute http(s) URLs; keep relative ones
|
||||||
|
if p.scheme in ("http", "https") and p.path:
|
||||||
|
data[k] = public_url(request, p.path)
|
||||||
|
except Exception:
|
||||||
|
# never fail formatting due to a bad URL
|
||||||
|
pass
|
||||||
|
|
||||||
# Tiny text builders for bot replies
|
# Tiny text builders for bot replies
|
||||||
def _text_sami(data: Dict[str, Any]) -> str:
|
def _text_sami(data: Dict[str, Any]) -> str:
|
||||||
if "beta" in data and "r2" in data:
|
if "beta" in data and "r2" in data:
|
||||||
@ -174,6 +209,7 @@ def format_sami(request: HttpRequest):
|
|||||||
payload, src = _extract_payload(body)
|
payload, src = _extract_payload(body)
|
||||||
status, data = _post_underlying("sami", payload, timeout=60.0)
|
status, data = _post_underlying("sami", payload, timeout=60.0)
|
||||||
data = data if isinstance(data, dict) else {"result": data}
|
data = data if isinstance(data, dict) else {"result": data}
|
||||||
|
_normalize_urls_to_public(data, request) # ensure public links
|
||||||
data.setdefault("_echo", {"src": src, "payload_keys": list(payload.keys())})
|
data.setdefault("_echo", {"src": src, "payload_keys": list(payload.keys())})
|
||||||
try:
|
try:
|
||||||
data["text"] = _text_sami(data)
|
data["text"] = _text_sami(data)
|
||||||
@ -188,6 +224,7 @@ def format_sites(request: HttpRequest):
|
|||||||
payload, src = _extract_payload(body)
|
payload, src = _extract_payload(body)
|
||||||
status, data = _post_underlying("sites", payload, timeout=60.0)
|
status, data = _post_underlying("sites", payload, timeout=60.0)
|
||||||
data = data if isinstance(data, dict) else {"result": data}
|
data = data if isinstance(data, dict) else {"result": data}
|
||||||
|
_normalize_urls_to_public(data, request) # ensure public links
|
||||||
data.setdefault("_echo", {"src": src, "payload_keys": list(payload.keys())})
|
data.setdefault("_echo", {"src": src, "payload_keys": list(payload.keys())})
|
||||||
try:
|
try:
|
||||||
data["text"] = _text_sites(data)
|
data["text"] = _text_sites(data)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user