fix: expose x-amz-storage-class in CORS response headers

The object info modal in the WebUI was always displaying STANDARD as the
storage class regardless of the actual value. The root cause is a browser
CORS restriction: when the WebUI makes a cross-origin HEAD request to the
S3 endpoint, the browser silently drops any response header not listed in
Access-Control-Expose-Headers, causing response.headers.get('x-amz-storage-class')
to return null and the UI to fall back to the hardcoded STANDARD default.

Adding x-amz-storage-class to the default set of exposed headers ensures
the browser makes it available to JavaScript, allowing storage classes such
as GLACIER to be correctly reflected in the UI.
This commit is contained in:
Ben McClelland
2026-05-29 20:13:17 -07:00
parent f7cc70b157
commit 0e165edfb1
3 changed files with 5 additions and 5 deletions
@@ -55,8 +55,8 @@ func TestApplyBucketCORS_FallbackOrigin_NoBucketCors_NoRequestOrigin(t *testing.
if got := resp.Header.Get("Access-Control-Allow-Origin"); got != origin {
t.Fatalf("expected Access-Control-Allow-Origin to be set to fallback, got %q", got)
}
if got := resp.Header.Get("Access-Control-Expose-Headers"); got != "ETag" {
t.Fatalf("expected Access-Control-Expose-Headers to include ETag, got %q", got)
if got := resp.Header.Get("Access-Control-Expose-Headers"); got != "ETag, x-amz-storage-class" {
t.Fatalf("expected Access-Control-Expose-Headers to include ETag and x-amz-storage-class, got %q", got)
}
}
+1 -1
View File
@@ -22,7 +22,7 @@ import (
func ensureExposeETag(ctx *fiber.Ctx) {
existing := strings.TrimSpace(string(ctx.Response().Header.Peek("Access-Control-Expose-Headers")))
defaults := []string{"ETag"}
defaults := []string{"ETag", "x-amz-storage-class"}
if existing == "" {
ctx.Response().Header.Add("Access-Control-Expose-Headers", strings.Join(defaults, ", "))
return
+2 -2
View File
@@ -43,8 +43,8 @@ func TestApplyDefaultCORS_AddsHeaderWhenOriginSet(t *testing.T) {
if got := resp.Header.Get("Access-Control-Allow-Origin"); got != origin {
t.Fatalf("expected fallback origin header, got %q", got)
}
if got := resp.Header.Get("Access-Control-Expose-Headers"); got != "ETag" {
t.Fatalf("expected expose headers to include ETag, got %q", got)
if got := resp.Header.Get("Access-Control-Expose-Headers"); got != "ETag, x-amz-storage-class" {
t.Fatalf("expected expose headers to include ETag and x-amz-storage-class, got %q", got)
}
}