diff --git a/weed/s3api/s3api_object_handlers.go b/weed/s3api/s3api_object_handlers.go index 2078d4e69c..877268dfb4 100644 --- a/weed/s3api/s3api_object_handlers.go +++ b/weed/s3api/s3api_object_handlers.go @@ -688,11 +688,16 @@ func newListEntry(s3a *S3ApiServer, entry *filer_pb.Entry, key string, dir strin // Determine ETag: prioritize ExtETagKey for versioned objects (supports multipart ETags), // then fall back to filer.ETag() which uses Md5 attribute or calculates from chunks etag := s3a.getObjectETag(entry) + size := int64(filer.FileSize(entry)) + if isDirectory && size == 0 { + // A trailing-slash key keeps its body inline in the directory entry, with no FileSize. + size = int64(len(entry.Content)) + } listEntry = ListEntry{ Key: key, LastModified: time.Unix(entry.Attributes.Mtime, 0).UTC(), ETag: etag, - Size: int64(filer.FileSize(entry)), + Size: size, StorageClass: StorageClass(storageClass), } if fetchOwner { diff --git a/weed/s3api/s3api_object_handlers_list_directory_marker_test.go b/weed/s3api/s3api_object_handlers_list_directory_marker_test.go index fe5ab2c7ed..d3b3789761 100644 --- a/weed/s3api/s3api_object_handlers_list_directory_marker_test.go +++ b/weed/s3api/s3api_object_handlers_list_directory_marker_test.go @@ -123,3 +123,19 @@ func TestDirectoryMarkersCostNoLookups(t *testing.T) { assert.Equal(t, []string{"d1", "d2", "d3"}, seen) assert.Equal(t, 1, client.calls, "listing directory markers must not cost a round trip per marker") } + +// TestDirectoryMarkerWithBodyListsItsSize covers a trailing-slash key PUT with a body: +// the body is kept inline in the directory entry, which has no FileSize, and GET/HEAD +// already report its length. +func TestDirectoryMarkerWithBodyListsItsSize(t *testing.T) { + s3a := &S3ApiServer{option: &S3ApiServerOption{BucketsPath: "/buckets"}} + entry := directoryMarker("m2") + entry.Content = []byte("marker body") + + listed := newListEntry(s3a, entry, "", "/buckets/test", "m2", "/buckets/test/", false, true, false) + assert.Equal(t, "m2/", listed.Key) + assert.Equal(t, int64(len("marker body")), listed.Size) + + listed = newListEntry(s3a, directoryMarker("m3"), "", "/buckets/test", "m3", "/buckets/test/", false, true, false) + assert.Equal(t, int64(0), listed.Size) +}