Skip to content

feat: Add filename field to Metadata#517

Merged
lcian merged 13 commits into
mainfrom
lcian/add-filename-metadata-field
Jun 26, 2026
Merged

feat: Add filename field to Metadata#517
lcian merged 13 commits into
mainfrom
lcian/add-filename-metadata-field

Conversation

@lcian

@lcian lcian commented Jun 23, 2026

Copy link
Copy Markdown
Member

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 Metadata field to the server and clients, which is send by clients as x-sn-filename and rendered in GET/HEAD responses via such a Content-Disposition header.

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

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>
@codecov

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>
Comment thread clients/rust/src/multipart.rs
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>
@lcian

This comment has been minimized.

Comment thread objectstore-server/src/endpoints/batch.rs Outdated
lcian and others added 2 commits June 23, 2026 20:26
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 lcian changed the title feat(types): Add filename field to Metadata feat: Add filename field to Metadata Jun 24, 2026
Comment thread objectstore-service/src/streaming.rs
@linear-code

linear-code Bot commented Jun 24, 2026

Copy link
Copy Markdown

FS-134

@lcian
lcian marked this pull request as ready for review June 24, 2026 07:59
@lcian
lcian requested a review from a team as a code owner June 24, 2026 07:59
@lcian

This comment has been minimized.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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.

Comment thread objectstore-types/src/metadata.rs Outdated
Comment thread clients/python/tests/test_e2e.py

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ 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.

Comment thread objectstore-server/src/endpoints/objects.rs
Comment thread clients/rust/src/put.rs
Comment thread clients/python/src/objectstore_client/metadata.py
@lcian
lcian requested a review from jan-auer June 25, 2026 12:35
@lcian
lcian merged commit 27b4d16 into main Jun 26, 2026
25 checks passed
@lcian
lcian deleted the lcian/add-filename-metadata-field branch June 26, 2026 09:11
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants