Spaces:
Running
Running
fix(a11oy): never proxy v1/warhacker + v1/observability to Node backend (local routes win); honest 404
Browse filesDeployed build proxied warhacker/obs to Node -> false 'not found'. serve.py now resolves these locally. Signed-off-by: Stephen P. Lutar Jr. <stephenlutar2@gmail.com>
serve.py
CHANGED
|
@@ -1048,6 +1048,9 @@ async def reason(request: Request) -> JSONResponse:
|
|
| 1048 |
except Exception:
|
| 1049 |
return JSONResponse({"error": "invalid JSON body"}, status_code=400)
|
| 1050 |
|
|
|
|
|
|
|
|
|
|
| 1051 |
action = body.get("action", body)
|
| 1052 |
if not isinstance(action, dict):
|
| 1053 |
return JSONResponse({"error": "expected {action: {...}} or flat action object"}, status_code=400)
|
|
@@ -2220,8 +2223,28 @@ except Exception as _wh_obs_e: # pragma: no cover - additive, defensive
|
|
| 2220 |
print(f"[a11oy] Warhacker+Observability NOT mounted ({_wh_obs_e!r}); existing routes unaffected", file=sys.stderr)
|
| 2221 |
|
| 2222 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2223 |
@app.api_route("/api/a11oy/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"])
|
| 2224 |
async def api_proxy(request: Request, path: str) -> Response:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2225 |
return await proxy_to_backend(request, f"/{path}")
|
| 2226 |
|
| 2227 |
|
|
|
|
| 1048 |
except Exception:
|
| 1049 |
return JSONResponse({"error": "invalid JSON body"}, status_code=400)
|
| 1050 |
|
| 1051 |
+
if not isinstance(body, dict):
|
| 1052 |
+
return JSONResponse({"error": "expected {action: {...}} or flat action object"}, status_code=400)
|
| 1053 |
+
|
| 1054 |
action = body.get("action", body)
|
| 1055 |
if not isinstance(action, dict):
|
| 1056 |
return JSONResponse({"error": "expected {action: {...}} or flat action object"}, status_code=400)
|
|
|
|
| 2223 |
print(f"[a11oy] Warhacker+Observability NOT mounted ({_wh_obs_e!r}); existing routes unaffected", file=sys.stderr)
|
| 2224 |
|
| 2225 |
|
| 2226 |
+
# Namespaces that are served LOCALLY by registered FastAPI routes above and have
|
| 2227 |
+
# NO counterpart on the Node backend. If a request for one of these ever reaches
|
| 2228 |
+
# this proxy, the local route failed to match (e.g. registration order regressed
|
| 2229 |
+
# after a partial rebuild) — proxying it would hit the Node backend and return a
|
| 2230 |
+
# misleading {"error":"not found","path":"/v1/..."}. Instead we answer honestly
|
| 2231 |
+
# here so the failure is self-documenting and never silently mis-attributed to
|
| 2232 |
+
# the organ. ADDITIVE, defensive: matches nothing in the normal (correct) path.
|
| 2233 |
+
_LOCAL_ONLY_A11OY_PREFIXES = ("v1/warhacker/", "v1/observability/")
|
| 2234 |
+
|
| 2235 |
+
|
| 2236 |
@app.api_route("/api/a11oy/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"])
|
| 2237 |
async def api_proxy(request: Request, path: str) -> Response:
|
| 2238 |
+
if path.startswith(_LOCAL_ONLY_A11OY_PREFIXES):
|
| 2239 |
+
return JSONResponse(
|
| 2240 |
+
{"error": "local route unmatched — not proxied to Node backend",
|
| 2241 |
+
"path": f"/api/a11oy/{path}",
|
| 2242 |
+
"hint": "this namespace is served in-process by a11oy_warhacker_obs.register(); "
|
| 2243 |
+
"a 404 here means its routes did not register before this proxy. "
|
| 2244 |
+
"Rebuild the Space from the merged build so the local routes load.",
|
| 2245 |
+
"warhacker_index": "/api/a11oy/v1/warhacker/index"},
|
| 2246 |
+
status_code=404,
|
| 2247 |
+
)
|
| 2248 |
return await proxy_to_backend(request, f"/{path}")
|
| 2249 |
|
| 2250 |
|