From 46b6bfdb9d05197ab7d4fb8ee914b5f46f3af924 Mon Sep 17 00:00:00 2001 From: theaux Date: Tue, 13 Oct 2026 10:27:24 +0700 Subject: [PATCH] messages: remove omitempty from IsTruncated in multipart results AWS S3 specifications require to always be present in ListMultipartUploadsResult and ListMultipartUploadPartsResult responses, even when false. Previously, xml:"IsTruncated,omitempty" caused Go's xml encoder to omit the tag when IsTruncated was false. This caused strict S3 clients (such as the AWS Go SDK used in Docker Distribution registry v2/v3) to unmarshal the field as a nil *bool, leading to a nil pointer dereference panic when checking *resp.IsTruncated. Matches existing behavior in ListBucketResultBase and ListBucketVersionsResult. Fixes #21 Ref rclone/rclone#10078 --- messages.go | 4 ++-- messages_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/messages.go b/messages.go index 51d724db..7558859d 100644 --- a/messages.go +++ b/messages.go @@ -395,7 +395,7 @@ type ListMultipartUploadsResult struct { Prefix string `xml:"Prefix,omitempty"` CommonPrefixes []CommonPrefix `xml:"CommonPrefixes,omitempty"` - IsTruncated bool `xml:"IsTruncated,omitempty"` + IsTruncated bool `xml:"IsTruncated"` Uploads []ListMultipartUploadItem `xml:"Upload"` } @@ -421,7 +421,7 @@ type ListMultipartUploadPartsResult struct { PartNumberMarker int `xml:"PartNumberMarker"` NextPartNumberMarker int `xml:"NextPartNumberMarker"` MaxParts int64 `xml:"MaxParts"` - IsTruncated bool `xml:"IsTruncated,omitempty"` + IsTruncated bool `xml:"IsTruncated"` Parts []ListMultipartUploadPartItem `xml:"Part"` } diff --git a/messages_test.go b/messages_test.go index afc971ae..26cd188c 100644 --- a/messages_test.go +++ b/messages_test.go @@ -3,6 +3,7 @@ package gofakes3 import ( "fmt" "io" + "strings" "testing" "time" @@ -180,3 +181,33 @@ func TestCopyObjectResult(t *testing.T) { t.Fatalf("unexpected XML output: %s", string(out)) } } + +func TestListMultipartUploadPartsResultIsTruncated(t *testing.T) { + res := ListMultipartUploadPartsResult{ + Bucket: "mybucket", + Key: "mykey", + UploadID: "upload123", + IsTruncated: false, + } + out, err := xml.Marshal(&res) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(string(out), "false") { + t.Fatalf("expected false in XML, got: %s", string(out)) + } +} + +func TestListMultipartUploadsResultIsTruncated(t *testing.T) { + res := ListMultipartUploadsResult{ + Bucket: "mybucket", + IsTruncated: false, + } + out, err := xml.Marshal(&res) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(string(out), "false") { + t.Fatalf("expected false in XML, got: %s", string(out)) + } +}