diff --git a/src/http/api.zig b/src/http/api.zig index 76d7a17..4d703b1 100644 --- a/src/http/api.zig +++ b/src/http/api.zig @@ -333,6 +333,10 @@ pub fn text(request: *Request, status: http.Status, body: []const u8) !void { res.body = try res.arena.dupe(u8, body); } +// writes the xrpc error body and fails with HandledResponse so the caller +// stops too. a guard like `return http_api.xrpcError(...)` inside a helper +// invoked with `try` used to return success after writing, and the handler +// went on to do the work and overwrite the error with a 200. pub fn xrpcError( request: *Request, status: http.Status, @@ -342,6 +346,7 @@ pub fn xrpcError( var buf: [512]u8 = undefined; const body = try std.fmt.bufPrint(&buf, "{{\"error\":\"{s}\",\"message\":\"{s}\"}}", .{ error_name, message }); try json(request, status, body); + return error.HandledResponse; } const json_headers = [_]http.Header{ diff --git a/tools/smoke.sh b/tools/smoke.sh index 787e846..6d3afd6 100755 --- a/tools/smoke.sh +++ b/tools/smoke.sh @@ -254,6 +254,22 @@ invalid_like_status=$(curl -sS -o /tmp/zds-invalid-like.json -w '%{http_code}' - test "$invalid_like_status" = "400" grep -q '"error":"InvalidRequest"' /tmp/zds-invalid-like.json +# a guard that writes an xrpc error must end the request. requireRepoMatches +# once wrote 400 and returned success, and createRecord went on to write the +# record and answer 200 over it. +wrong_repo_body="${TMPDIR:-/tmp}/zds-smoke-wrong-repo.json" +wrong_repo_status=$(curl -sS -o "$wrong_repo_body" -w '%{http_code}' -X POST "$base/xrpc/com.atproto.repo.createRecord" \ + -H "authorization: Bearer $token" \ + -H 'content-type: application/json' \ + --data '{"repo":"did:plc:someoneelse","collection":"app.bsky.feed.post","record":{"$type":"app.bsky.feed.post","text":"must not land","createdAt":"2026-05-22T00:00:03.000Z"}}') +test "$wrong_repo_status" = "400" +grep -q '"error":"InvalidRepo"' "$wrong_repo_body" +! curl -fsS "$base/xrpc/com.atproto.repo.listRecords?repo=did:plc:smoketest&collection=app.bsky.feed.post&limit=10" | grep -q 'must not land' +# and a 404 from requirePublicRepoAvailable stays a 404 rather than a 500 +missing_repo_status=$(curl -sS -o "$wrong_repo_body" -w '%{http_code}' "$base/xrpc/com.atproto.repo.getRecord?repo=did:plc:nobody&collection=app.bsky.feed.post&rkey=3zds") +test "$missing_repo_status" = "404" +grep -q '"error":"RepoNotFound"' "$wrong_repo_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"'