betterwithage commited on
Commit
a83686a
·
verified ·
1 Parent(s): 9f1da6c

fix(a11oy): never proxy v1/warhacker + v1/observability to Node backend (local routes win); honest 404

Browse files

Deployed 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>

Files changed (1) hide show
  1. serve.py +23 -0
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