From 31196a0367b73b229353cb7c4a5f141efd94e2d7 Mon Sep 17 00:00:00 2001 From: Zakaria Date: Sat, 24 Oct 2026 13:58:20 -0400 Subject: [PATCH] fix(s3): open an object's metadata and body stream together for CloudFront The streaming change from upstream (#5278) serves S3 origins through S3Service.openObject, which upstream added in a larger disk-streaming rework (#4691) not taken here. This adds the same method on top of the existing openObjectStream. --- .../hectorvent/floci/services/s3/S3Service.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/io/github/hectorvent/floci/services/s3/S3Service.java b/src/main/java/io/github/hectorvent/floci/services/s3/S3Service.java index e018eb9..f9a42b9 100644 --- a/src/main/java/io/github/hectorvent/floci/services/s3/S3Service.java +++ b/src/main/java/io/github/hectorvent/floci/services/s3/S3Service.java @@ -1332,6 +1332,23 @@ public class S3Service implements Resettable, ResourceProvider { } } + /** An object's metadata together with an open stream of its body; the caller closes it. */ + public record ObjectRead(S3Object object, InputStream body) implements java.io.Closeable { + @Override + public void close() throws IOException { + body.close(); + } + } + + /** + * Like {@link #getObject}, but the body is an open stream instead of a byte array, so a large + * object is served without being read into the heap. + */ + public ObjectRead openObject(String bucketName, String key, String versionId) { + S3Object object = getObjectMetadata(bucketName, key, versionId); + return new ObjectRead(object, openObjectStream(bucketName, key, versionId)); + } + public InputStream openObjectStream(String bucketName, String key, String versionId) { getObjectMetadata(bucketName, key, versionId); String bucketOwnerAccount = resolveBucketEntry(bucketName)