Open binary file URL as a card without 415 or hung spinner#4832
Open binary file URL as a card without 415 or hung spinner#4832richardhjtan wants to merge 3 commits into
Conversation
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.
Preview deploymentsHost Test Results 1 files ± 0 1 suites ±0 1h 30m 56s ⏱️ + 6m 28s Results for commit 3a5e473. ± Comparison against earlier commit 85303ec. For more details on these errors, see this check. Realm Server Test Results 1 files ± 0 1 suites ±0 8m 26s ⏱️ -48s Results for commit 3a5e473. ± Comparison against earlier commit 85303ec. For more details on these errors, see this check. |
a54b7f5 to
5668884
Compare
…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>
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>
A stack item opened directly from the URL bar (no `type:"file"` in the operator state) defaulted to `type:"card"` and dispatched through getCardInstance. For an uploaded binary (e.g. `.png`) the realm-server now returns a file-meta JSON document — getCardInstance rejected it as "non card document" and the spinner hung on "Loading card...". Two changes: - runtime-common: export `isFileDefExtension(filenameOrPath)`, backed by the existing FILEDEF_CODE_REF_BY_EXTENSION map so the set of recognized extensions stays in one place. - host stack-item: when no explicit type is provided, infer `type:"file"` from the id via `isFileDefExtension`. Pasted-URL opens of `.png` / `.svg` / `.gts` / etc. now go through the file-meta load path from the start. Also adds a safety net in store.getCardInstance: if a caller still manages to invoke it with a binary URL, the file-meta JSON response is rerouted through getFileMetaInstance instead of throwing a confusing "non card document" error. CS-11147 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
85303ec to
3a5e473
Compare
Summary
Opening a binary file URL (an uploaded
.png,.jpg, …) as a card — by pasting it into the operator-mode URL bar, or via any code path that routes throughgetCardInstance— fails today: realm-server returns415 Unsupported Media Type, or the host "Loading card…" spinner hangs with no surfaced error. Three coordinated changes get the file-meta load path taken end-to-end.Linear: CS-11147
Changes
file-metaJSON for binary GETs withAccept: application/vnd.card+jsoninstead of 415. Callers can discriminate viadata.type === "file-meta".card+markdownon a binary still 415s — markdown can't represent a binary. Touches the threenonJsonFileExistsbranches ingetCardinpackages/runtime-common/realm.ts.type:"file"from the URL extension when none is provided. NewisFileDefExtension()helper exported frompackages/runtime-common/file-def-code-ref.ts, backed by the existingFILEDEF_CODE_REF_BY_EXTENSIONmap so the set of recognized extensions stays in one place. Pasting a.pngURL into the URL bar now takes the file-meta load path from the first request.store.getCardInstance— if anything still asksgetCardInstancefor a URL that turns out to be a binary, the file-meta JSON is rerouted throughgetFileMetaInstanceand the in-flight card deferred resolves with that result. No hung spinner, no cryptic error.Files
packages/runtime-common/realm.tspackages/runtime-common/file-def-code-ref.ts— newisFileDefExtensionexportpackages/host/app/lib/stack-item.tspackages/host/app/services/store.tspackages/realm-server/tests/card-endpoints-test.ts— asserts file-meta JSON return forcard+jsonon a binary, retains 415 forcard+markdown, retains 415 forPATCH/DELETETest plan
pnpm lint:typesgreen acrossruntime-commonandhost(it is)..pngURL from a realm into a fresh tab. Pre-fix → hang or 415. Post-fix → the FileDef renders as an image.type:"file").Out of scope
Other failure modes from the broader broken-image investigation: CS-11144 (auth-SW token race, shipped #4828), CS-11146 (shipped #4829), CS-11145 (regression test in #4830, fix TBD).
🤖 Generated with Claude Code