From d30d1b7273572252afdd4f80327989df78aff9f8 Mon Sep 17 00:00:00 2001 From: zzstoatzz Date: Tue, 25 Aug 2026 10:31:40 -0500 Subject: [PATCH] http: catch HandledResponse on the xrpc proxy path; 500-mask regression in smoke MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the proxy branch in serveRequest calls xrpcProxy with a bare try, but the error.HandledResponse => {} catch only wraps app.dispatch. so every xrpcError inside the proxy path — most visibly the 401 InvalidToken from requireBearerAccess — propagated up to handle(), which overwrote the already-written json error with a plain-text 500 "Internal Server Error". clients (noti's updateSeen fan-out) saw unparseable 500s instead of the 401 that would trigger a token refresh. regression from 845202e, which made xrpcError terminate via HandledResponse but only taught dispatch to catch it. tools/smoke.sh asserts a proxied updateSeen with a bad token is a 401 InvalidToken json body; it fails on the previous code. Co-Authored-By: Claude Fable 5 --- src/http/server.zig | 5 ++++- tools/smoke.sh | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/http/server.zig b/src/http/server.zig index 9b925cf..228908f 100644 --- a/src/http/server.zig +++ b/src/http/server.zig @@ -70,7 +70,10 @@ const App = struct { telemetry_route = .proxy_xrpc; telemetry_class = .proxy; telemetry_label = stripQuery(request.url.raw); - try atproto_proxy.xrpcProxy(request); + atproto_proxy.xrpcProxy(request) catch |err| switch (err) { + error.HandledResponse => {}, + else => return err, + }; handler_failed = false; return; } diff --git a/tools/smoke.sh b/tools/smoke.sh index 6d3afd6..7272a7b 100755 --- a/tools/smoke.sh +++ b/tools/smoke.sh @@ -270,6 +270,18 @@ missing_repo_status=$(curl -sS -o "$wrong_repo_body" -w '%{http_code}' "$base/xr test "$missing_repo_status" = "404" grep -q '"error":"RepoNotFound"' "$wrong_repo_body" +# the xrpc proxy path bypasses dispatch, so its HandledResponse must be caught +# there too: a bad token on a proxied method is a 401 InvalidToken json body, +# never a plain-text 500 (the top-level handler once overwrote it). +proxy_body="${TMPDIR:-/tmp}/zds-smoke-proxy.json" +proxy_status=$(curl -sS -o "$proxy_body" -w '%{http_code}' -X POST "$base/xrpc/app.bsky.notification.updateSeen" \ + -H "authorization: Bearer not-a-real-token" \ + -H 'atproto-proxy: did:web:api.bsky.app#bsky_appview' \ + -H 'content-type: application/json' \ + --data '{"seenAt":"2026-05-22T00:00:03.000Z"}') +test "$proxy_status" = "401" +grep -q '"error":"InvalidToken"' "$proxy_body" + records=$(curl -fsS "$base/xrpc/com.atproto.repo.listRecords?repo=did:plc:smoketest&collection=app.bsky.feed.post&limit=10") printf '%s' "$records" | grep -q '"text":"smoke"' -- 2.51.2