Realm: GET binary file with card Accept falls through to file handler#4832
Realm: GET binary file with card Accept falls through to file handler#4832richardhjtan wants to merge 2 commits into
Conversation
…handler A GET request with Accept: application/vnd.card+json (or .card+markdown) targeting a path that holds a non-JSON file (typically an uploaded binary like .png) used to return 415 Unsupported Media Type. Callers that produced this mismatch ended up with a broken image / unusable response. Route these through fallbackHandle, which serves the file with inferContentType(...) on the response. Read-only handlers only: PATCH (3910) and DELETE (4507) still 415 because writing or deleting a binary as a card is genuinely wrong. CS-11147 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adjusts realm card read handling so GET requests for non-JSON files made with card-oriented Accept headers can fall through to the normal file-serving path instead of returning 415.
Changes:
- Routes missing card JSON index entries for existing non-JSON files through
fallbackHandle. - Applies the same fallback behavior to card markdown reads.
- Leaves write/delete card handlers unchanged for binary files.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Host Test Results 1 files ±0 1 suites ±0 1h 27m 23s ⏱️ - 17m 7s Results for commit 5668884. ± Comparison against earlier commit a54b7f5. Realm Server Test Results 1 files ± 0 1 suites ±0 9m 26s ⏱️ - 1m 24s Results for commit 5668884. ± Comparison against earlier commit a54b7f5. For more details on these errors, see this check. |
| if (!entry) { | ||
| if (await this.nonJsonFileExists(localPath)) { | ||
| return unsupportedMediaType(request, requestContext); | ||
| return this.fallbackHandle(request, requestContext); |
| if (instanceEntry === undefined) { | ||
| if (await this.nonJsonFileExists(localPath)) { | ||
| return unsupportedMediaType(request, requestContext); | ||
| return this.fallbackHandle(request, requestContext); |
The existing regression test asserted GET /greeting.txt with Accept: application/vnd.card+json returned 415. After the fallback change, GET should serve the file with its native content-type instead. Splits the test in two: GET is the new positive case; PATCH/DELETE still 415. CS-11147 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
a54b7f5 to
5668884
Compare
Summary
A GET request with
Accept: application/vnd.card+json(or.card+markdown) targeting a path that holds a non-JSON file (typically an uploaded binary like a.png) used to return 415 Unsupported Media Type. Callers ended up with a broken response.Route those through
fallbackHandle, which serves the file withinferContentType(...)as the content-type. Read-only handlers only —PATCHandDELETEon a binary still return 415 because writing or deleting a binary as a card is genuinely wrong.Part of a broader broken-image investigation. Full report shared separately.
Linear: CS-11147
What this fixes
When an internal caller mis-routes a binary file URL through a card-JSON or card-markdown pipeline (e.g. a host code path that lazily resolves a relationship and assumes the target is a card), the realm-server previously returned 415. The caller had no graceful path back to the bytes. Falling through to the file handler returns the binary with its native content-type, so any caller that inspects content-type can decide what to do, and any caller that just wants the bytes is unblocked.
This is a server-side leniency change, not a behavior change for legitimate card requests — the fallback only fires when an index entry does not exist and the path holds a non-JSON file.
Files
packages/runtime-common/realm.ts— three 415 → fallback edits in thegetCardJson(ETag fast path + main path) andgetCardMarkdownhandlers.Test plan
pnpm lint:typesgreen (it is).curl -H 'Accept: application/vnd.card+json' <realm>/path/to/foo.pngagainst staging post-deploy; expect 200 withContent-Type: image/pngand the binary body. Pre-fix returned 415.Out of scope
Other failure modes from the same investigation: CS-11144 (shipped #4828), CS-11146 (shipped #4829), CS-11145 (regression test in #4830, fix still TBD).
🤖 Generated with Claude Code