Skip to content

feat: support request headers as S3 object metadata in PUT templates#678

Merged
oxyno-zeta merged 1 commit intooxyno-zeta:masterfrom
argos83:put-request-headers-as-metadata
Feb 26, 2026
Merged

feat: support request headers as S3 object metadata in PUT templates#678
oxyno-zeta merged 1 commit intooxyno-zeta:masterfrom
argos83:put-request-headers-as-metadata

Conversation

@argos83
Copy link
Contributor

@argos83 argos83 commented Feb 19, 2026

Issue/Feature

Adds support for forwarding PUT request headers as S3 object metadata via Go templates. This enables use cases such as attaching tracing/correlation data or uploader identity to S3 objects at upload time.

In my particular case s3-proxy is accessed via a tool running in CI which needs to include metadata for git-commit and build-url to objects store in S3. Without this change there's no way to pass custom dynamic values for object metadata.

Additional Information

What: PutInput now exposes RequestHeaders (http.Header) so that PUT metadata and storage
class templates can access incoming request headers.

How: Templates use .Input.RequestHeaders.Get "X-Header-Name" for case-insensitive single-value
access, or {{ join "," (index .Input.RequestHeaders "X-Header-Name") }} to retrieve all values of a
multi-value header (via Sprig's join).

Example configuration:

metadata:
  uploaded-by: '{{ .Input.RequestHeaders.Get "X-Uploaded-By" }}'
  correlation-id: '{{ .Input.RequestHeaders.Get "X-Correlation-Id" }}'

GET/HEAD responses already exposed S3 metadata via .StreamFile.Metadata; this change closes the gap
on the PUT side.

Verification Steps

  1. Configure a target with a put action and a metadata template using .Input.RequestHeaders.Get "X-My-Header"
  2. Upload a file via PUT, passing X-My-Header: some-value in the request
  3. Check the uploaded S3 object's metadata — x-my-header should be set to some-value

Checklist:

  • Verified by team member
  • Tests were added
  • Comments where necessary (preferred self-explanatory code and tests over comments)
  • Documentation changes if necessary

@github-actions github-actions bot added documentation Improvements or additions to documentation tests labels Feb 19, 2026
@argos83 argos83 force-pushed the put-request-headers-as-metadata branch 2 times, most recently from bb3c692 to 51f2687 Compare February 19, 2026 12:51
@sebastian-tello
Copy link

Hi @oxyno-zeta, I was wondering if there could be a review of this PR any time soon. I'm really looking forward to get this feature released. Thanks!

@oxyno-zeta
Copy link
Owner

Hello @argos83 @sebastian-tello ,

Thanks for your PR. This can be cool yes !

Look like the documentation isn't fully updated as structure.md and templates.md are laking this part. Moreover, your changes also affect the systemMetadata part.
Can you update your PR with those changes ?

Unfortunately I won't have a lot of time this week @sebastian-tello . I have personally issues to manage for the moment...
I will check the code and other impacts later. Hope today or tomorrow morning.

Have a nice day !

@argos83 argos83 force-pushed the put-request-headers-as-metadata branch 2 times, most recently from 089d6f4 to 4db2233 Compare February 23, 2026 11:09
@sebastian-tello
Copy link

Hello @argos83 @sebastian-tello ,

Thanks for your PR. This can be cool yes !

Look like the documentation isn't fully updated as structure.md and templates.md are laking this part. Moreover, your changes also affect the systemMetadata part. Can you update your PR with those changes ?

Unfortunately I won't have a lot of time this week @sebastian-tello . I have personally issues to manage for the moment... I will check the code and other impacts later. Hope today or tomorrow morning.

Have a nice day !

Thanks for your feedback @oxyno-zeta . I hadn't noticed this affecting systemMetadata too. I see the value of this too, systemMetadata fields were originally meant for fixed config-level values. Some reasonable use cases for RequestHeaders in systemMetadata:

  • contentLanguage: '{{ .Input.RequestHeaders.Get "Content-Language" }}' — client declares the language of
    what they're uploading
  • contentEncoding: '{{ .Input.RequestHeaders.Get "Content-Encoding" }}' — client uploads a pre-compressed
    file and signals it
  • contentDisposition: '{{ .Input.RequestHeaders.Get "X-Content-Disposition" }}' — client controls download
    filename

The less natural ones are cacheControl and expires (those are usually a server/config policy decision, not
something a client should dictate).

I have updated the docs as you suggested to reflect this changes.

@oxyno-zeta
Copy link
Owner

oxyno-zeta commented Feb 23, 2026

I've started the CI for the first part. I will start it again with the missing test.

But this is a cool feature to have :) . Thanks !

Add RequestHeaders (http.Header) to PutInput so that PUT metadata and
storage class templates can access incoming request headers via
.Input.RequestHeaders.Get. The lookup is case-insensitive, matching
Go's standard http.Header semantics. Multi-value headers can be accessed
with index and combined using sprig's join function.
@argos83 argos83 force-pushed the put-request-headers-as-metadata branch from 4db2233 to 7a3b0ac Compare February 24, 2026 08:27
@argos83
Copy link
Contributor Author

argos83 commented Feb 24, 2026

I've started the CI for the first part. I will start it again with the missing test.

But this is a cool feature to have :) . Thanks !

Test added 😊

Btw, I've been amending and force-pushing the same commit to keep implementation, docs, and tests as a single atomic changeset - wasn't sure how automated releases/changelog from conventional commits work in this project. Let me know if you'd prefer a different approach for future contributions.

@oxyno-zeta
Copy link
Owner

oxyno-zeta commented Feb 24, 2026

Hello @argos83 ,
Thanks for the new test.
No problem for the force push. That's great like that as this is a full feature.
This looks good to me but I'm not available to release it now sorry. Hope thursday or next monday.
Have a nice day !

@oxyno-zeta oxyno-zeta merged commit c2c1780 into oxyno-zeta:master Feb 26, 2026
11 of 12 checks passed
@oxyno-zeta
Copy link
Owner

🎉 This PR is included in version 4.20.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation released tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants