From 38d2881d59d418cc6f9b3b6922eb76793f390a22 Mon Sep 17 00:00:00 2001 From: Andrew Gaul Date: Sun, 27 Oct 2024 19:39:31 -0700 Subject: [PATCH] Support condition get object in azureblob-sdk References #606. --- .../s3proxy/azureblob/AzureBlobStore.java | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/gaul/s3proxy/azureblob/AzureBlobStore.java b/src/main/java/org/gaul/s3proxy/azureblob/AzureBlobStore.java index d87e08c..1eb189b 100644 --- a/src/main/java/org/gaul/s3proxy/azureblob/AzureBlobStore.java +++ b/src/main/java/org/gaul/s3proxy/azureblob/AzureBlobStore.java @@ -21,6 +21,7 @@ import java.io.InputStream; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.time.OffsetDateTime; +import java.time.ZoneOffset; import java.util.Base64; import java.util.Date; import java.util.List; @@ -28,6 +29,8 @@ import java.util.Map; import java.util.Set; import java.util.UUID; +import javax.annotation.Nullable; + import com.azure.core.credential.AzureNamedKeyCredential; import com.azure.storage.blob.BlobServiceClient; import com.azure.storage.blob.BlobServiceClientBuilder; @@ -36,6 +39,8 @@ import com.azure.storage.blob.models.BlobErrorCode; import com.azure.storage.blob.models.BlobHttpHeaders; import com.azure.storage.blob.models.BlobListDetails; import com.azure.storage.blob.models.BlobProperties; +import com.azure.storage.blob.models.BlobRange; +import com.azure.storage.blob.models.BlobRequestConditions; import com.azure.storage.blob.models.BlobStorageException; import com.azure.storage.blob.models.BlockListType; import com.azure.storage.blob.models.ListBlobsOptions; @@ -213,7 +218,16 @@ public final class AzureBlobStore extends BaseBlobStore { public Blob getBlob(String container, String key, GetOptions options) { var client = blobServiceClient.getBlobContainerClient(container) .getBlobClient(key); - var blobStream = client.openInputStream(); + // TODO: handle BlobRange + BlobRange range = null; + var conditions = new BlobRequestConditions() + .setIfMatch(options.getIfMatch()) + .setIfModifiedSince(toOffsetDateTime( + options.getIfModifiedSince())) + .setIfNoneMatch(options.getIfNoneMatch()) + .setIfUnmodifiedSince(toOffsetDateTime( + options.getIfUnmodifiedSince())); + var blobStream = client.openInputStream(range, conditions); var properties = blobStream.getProperties(); var expires = properties.getExpiresOn(); return new BlobBuilderImpl() @@ -265,7 +279,13 @@ public final class AzureBlobStore extends BaseBlobStore { azureOptions, /*context=*/ null)) { is.transferTo(os); } - return ""; // TODO: how to get ETag? + + // TODO: racy + return blobServiceClient + .getBlobContainerClient(container) + .getBlobClient(blob.getMetadata().getName()) + .getProperties() + .getETag(); } catch (IOException ioe) { throw new RuntimeException(ioe); } @@ -513,11 +533,20 @@ public final class AzureBlobStore extends BaseBlobStore { return S3ErrorCode.NO_SUCH_KEY; } else if (code.equals(BlobErrorCode.CONTAINER_NOT_FOUND)) { return S3ErrorCode.NO_SUCH_BUCKET; + } else if (code == BlobErrorCode.CONDITION_NOT_MET) { + return S3ErrorCode.PRECONDITION_FAILED; } else { return S3ErrorCode.INTERNAL_ERROR; } } + private static OffsetDateTime toOffsetDateTime(@Nullable Date date) { + if (date == null) { + return null; + } + return date.toInstant().atOffset(ZoneOffset.UTC); + } + private static Date toDate(OffsetDateTime time) { return new Date(time.toInstant().toEpochMilli()); }