feat: Add filename field to Metadata#517
Merged
Merged
Conversation
Add an optional filename field to Metadata, transmitted via the x-sn-filename header. When present, the server emits a Content-Disposition: attachment; filename="<filename>" header on GET and HEAD responses for browser/download-tool compatibility. - Add filename field to Metadata struct with serde and header support - Map to GCS native contentDisposition field - Emit Content-Disposition on GET, HEAD, and batch HEAD responses - Add .filename() builder methods to Rust client PutBuilder and InitiateMultipartBuilder - Add filename parameter to Python client put() and initiate_multipart_upload() Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
Adding the filename field to Metadata pushed the Insert variant past clippy's large_enum_variant threshold (232 bytes vs 24 for the next largest). Box it to keep the enum small on the stack. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
The filename escaping only escaped double quotes but not backslashes, allowing a stored filename with a backslash-quote sequence to terminate the quoted-string and inject extra Content-Disposition parameters. Centralize format_content_disposition and parse_content_disposition in objectstore-types so all call sites share correct escaping of both backslash and double-quote characters (in the right order). Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
This comment has been minimized.
This comment has been minimized.
Content-Disposition is used by the multipart framing itself to delimit parts, so setting it on individual batch response parts would conflict. Clients should read the filename from the x-sn-filename metadata header instead, which to_headers() already emits. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
Add filename assertions to existing e2e tests in both clients to verify the field roundtrips through PUT and GET (including batch GET in the Rust client). Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
lcian
commented
Jun 24, 2026
lcian
marked this pull request as ready for review
June 24, 2026 07:59
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 0699e52. Configure here.
jan-auer
reviewed
Jun 24, 2026
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7f0a254. Configure here.
jan-auer
approved these changes
Jun 25, 2026
jan-auer
added a commit
that referenced
this pull request
Jul 3, 2026
* origin/main: (99 commits) fix(server): Ignore client-supplied read-only metadata on writes (#535) fix(stresstest): Use `put_path` for `many` requests (#533) fix(server): Strip Kubernetes hashes from downstream service (#530) ci: Scope sentry-options secrets instead of inherit (#534) build(client): Remove version pin notice on tokio dependency (#531) ref(server): Capture errors from backend servers in Sentry (#525) fix(server): Remove service tag from request metric (#528) fix(sentry): Bind hub to response bodies via middleware (#526) build: Disable in-process symbolication for heap profiles (#527) fix(dev): Only pass profiling feature for objectstore-server (#523) feat(server): Add on-demand heap profiling endpoints (#522) feat: Add filename field to Metadata (#517) docs: Fix and expand documentation across the workspace (#521) fix: Replace lossy casts with safer integer idioms (#518) build(deps): bump sentry to 0.48.3 (#520) ref(server): Skip auth checks when not configured (#519) feat(client): Accept optional tokens in ClientBuilder::token (#516) fix: Remove needless return statements in tiered backend tests (#514) fix: Use jemalloc only on linux (#515) fix: Apply pedantic Clippy lints across workspace (#513) ... # Conflicts: # Cargo.lock # Cargo.toml # README.md # objectstore-server/Cargo.toml # objectstore-server/src/extractors/id.rs # objectstore-server/src/killswitches.rs # objectstore-server/tests/limits.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

For Debug Files, the current Sentry endpoint returns a
Content-Disposition: attachment; filename="<filename>"header, which prompts browsers to save the file under the given name.Objectstore doesn't currently return this, so if we want downloads from e.g. the UI to go directly to Objectstore, the user will likely be prompted with the Objectstore key as the filename, which doesn't necessarily match the logical filename we show e.g. in the UI itself.
This introduces a first-class
Metadatafield to the server and clients, which is send by clients asx-sn-filenameand rendered in GET/HEAD responses via such aContent-Dispositionheader.This field can be an arbitrary
String.When deserializing it into a
Content-Disposition, we perform escaping and normalization of path separators and filenames containing only dots.Close FS-134