Skip to content

Commit 24f03d7

Browse files
authored
STG100 - Get and Set Blob Tags Conditional Headers (#46406)
* generating off swagger * wip * proper implementation added * adding tests and recordings * adding new headers to recording ignore list * regenerating off swagger and adding listblob starts from implementation back * fixing position of startsfrom in implementations * fixing formatting * fixing formatting again * updating recordings
1 parent 0d34468 commit 24f03d7

File tree

8 files changed

+413
-61
lines changed

8 files changed

+413
-61
lines changed

sdk/storage/azure-storage-blob/assets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
"AssetsRepo": "Azure/azure-sdk-assets",
33
"AssetsRepoPrefixPath": "java",
44
"TagPrefix": "java/storage/azure-storage-blob",
5-
"Tag": "java/storage/azure-storage-blob_26d22d7fb8"
5+
"Tag": "java/storage/azure-storage-blob_578b4adb58"
66
}

sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/implementation/BlobsImpl.java

Lines changed: 251 additions & 49 deletions
Large diffs are not rendered by default.

sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/BlobAsyncClientBase.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1998,7 +1998,9 @@ Mono<Response<Map<String, String>>> getTagsWithResponse(BlobGetTagsOptions optio
19981998
= (options.getRequestConditions() == null) ? new BlobRequestConditions() : options.getRequestConditions();
19991999
return this.azureBlobStorage.getBlobs()
20002000
.getTagsWithResponseAsync(containerName, blobName, null, null, snapshot, versionId,
2001-
requestConditions.getTagsConditions(), requestConditions.getLeaseId(), context)
2001+
requestConditions.getTagsConditions(), requestConditions.getLeaseId(),
2002+
requestConditions.getIfModifiedSince(), requestConditions.getIfUnmodifiedSince(),
2003+
requestConditions.getIfMatch(), requestConditions.getIfNoneMatch(), context)
20022004
.map(response -> {
20032005
Map<String, String> tags = new HashMap<>();
20042006
for (BlobTag tag : response.getValue().getBlobTagSet()) {
@@ -2077,7 +2079,9 @@ Mono<Response<Void>> setTagsWithResponse(BlobSetTagsOptions options, Context con
20772079
BlobTags t = new BlobTags().setBlobTagSet(tagList);
20782080
return this.azureBlobStorage.getBlobs()
20792081
.setTagsNoCustomHeadersWithResponseAsync(containerName, blobName, null, versionId, null, null, null,
2080-
requestConditions.getTagsConditions(), requestConditions.getLeaseId(), t, context);
2082+
requestConditions.getTagsConditions(), requestConditions.getLeaseId(),
2083+
requestConditions.getIfModifiedSince(), requestConditions.getIfUnmodifiedSince(),
2084+
requestConditions.getIfMatch(), requestConditions.getIfNoneMatch(), t, context);
20812085
}
20822086

20832087
/**

sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/BlobClientBase.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1953,7 +1953,9 @@ public Response<Map<String, String>> getTagsWithResponse(BlobGetTagsOptions opti
19531953

19541954
Callable<ResponseBase<BlobsGetTagsHeaders, BlobTags>> operation = () -> this.azureBlobStorage.getBlobs()
19551955
.getTagsWithResponse(containerName, blobName, null, null, snapshot, versionId,
1956-
requestConditions.getTagsConditions(), requestConditions.getLeaseId(), finalContext);
1956+
requestConditions.getTagsConditions(), requestConditions.getLeaseId(),
1957+
requestConditions.getIfModifiedSince(), requestConditions.getIfUnmodifiedSince(),
1958+
requestConditions.getIfMatch(), requestConditions.getIfNoneMatch(), finalContext);
19571959

19581960
ResponseBase<BlobsGetTagsHeaders, BlobTags> response
19591961
= sendRequest(operation, timeout, BlobStorageException.class);
@@ -2026,7 +2028,9 @@ public Response<Void> setTagsWithResponse(BlobSetTagsOptions options, Duration t
20262028
BlobTags t = new BlobTags().setBlobTagSet(tagList);
20272029
Callable<Response<Void>> operation = () -> this.azureBlobStorage.getBlobs()
20282030
.setTagsNoCustomHeadersWithResponse(containerName, blobName, null, versionId, null, null, null,
2029-
requestConditions.getTagsConditions(), requestConditions.getLeaseId(), t, finalContext);
2031+
requestConditions.getTagsConditions(), requestConditions.getLeaseId(),
2032+
requestConditions.getIfModifiedSince(), requestConditions.getIfUnmodifiedSince(),
2033+
requestConditions.getIfMatch(), requestConditions.getIfNoneMatch(), t, finalContext);
20302034
return sendRequest(operation, timeout, BlobStorageException.class);
20312035
}
20322036

sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobApiTests.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1663,6 +1663,71 @@ private static Stream<Arguments> setTagsACSupplier() {
16631663
return Stream.of(Arguments.of((String) null), Arguments.of("\"foo\" = 'bar'"));
16641664
}
16651665

1666+
@RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-02-06")
1667+
@ParameterizedTest
1668+
@MethodSource("com.azure.storage.blob.BlobTestBase#allConditionsSupplier")
1669+
public void setGetTagOptionsAC(OffsetDateTime modified, OffsetDateTime unmodified, String match, String noneMatch,
1670+
String leaseID) {
1671+
Map<String, String> t = new HashMap<>();
1672+
1673+
t.put("foo", "bar");
1674+
1675+
match = setupBlobMatchCondition(bc, match);
1676+
leaseID = setupBlobLeaseCondition(bc, leaseID);
1677+
BlobRequestConditions bac = new BlobRequestConditions().setLeaseId(leaseID)
1678+
.setIfMatch(match)
1679+
.setIfNoneMatch(noneMatch)
1680+
.setIfModifiedSince(modified)
1681+
.setIfUnmodifiedSince(unmodified);
1682+
1683+
assertResponseStatusCode(
1684+
bc.setTagsWithResponse(new BlobSetTagsOptions(t).setRequestConditions(bac), null, Context.NONE), 204);
1685+
assertResponseStatusCode(
1686+
bc.getTagsWithResponse(new BlobGetTagsOptions().setRequestConditions(bac), null, Context.NONE), 200);
1687+
}
1688+
1689+
@RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-02-06")
1690+
@ParameterizedTest
1691+
@MethodSource("com.azure.storage.blob.BlobTestBase#allConditionsFailSupplier")
1692+
public void setTagOptionsACFail(OffsetDateTime modified, OffsetDateTime unmodified, String match, String noneMatch,
1693+
String leaseID, String tags) {
1694+
Map<String, String> t = new HashMap<>();
1695+
1696+
//The x-ms-if-tags-request header is not supported
1697+
t.put("notfoo", "notbar");
1698+
1699+
noneMatch = setupBlobMatchCondition(bc, noneMatch);
1700+
1701+
BlobRequestConditions bac = new BlobRequestConditions().setLeaseId(leaseID)
1702+
.setIfMatch(match)
1703+
.setIfNoneMatch(noneMatch)
1704+
.setIfModifiedSince(modified)
1705+
.setIfUnmodifiedSince(unmodified)
1706+
.setTagsConditions(tags);
1707+
1708+
assertThrows(BlobStorageException.class,
1709+
() -> bc.setTagsWithResponse(new BlobSetTagsOptions(t).setRequestConditions(bac), null, Context.NONE));
1710+
}
1711+
1712+
@RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-02-06")
1713+
@ParameterizedTest
1714+
@MethodSource("com.azure.storage.blob.BlobTestBase#allConditionsFailSupplier")
1715+
public void getTagOptionsACFail(OffsetDateTime modified, OffsetDateTime unmodified, String match, String noneMatch,
1716+
String leaseID, String tags) {
1717+
//The x-ms-if-tags-request header is not supported
1718+
1719+
noneMatch = setupBlobMatchCondition(bc, noneMatch);
1720+
BlobRequestConditions bac = new BlobRequestConditions().setLeaseId(leaseID)
1721+
.setIfMatch(match)
1722+
.setIfNoneMatch(noneMatch)
1723+
.setIfModifiedSince(modified)
1724+
.setIfUnmodifiedSince(unmodified)
1725+
.setTagsConditions(tags);
1726+
1727+
assertThrows(BlobStorageException.class,
1728+
() -> bc.getTagsWithResponse(new BlobGetTagsOptions().setRequestConditions(bac), null, Context.NONE));
1729+
}
1730+
16661731
@RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2019-07-07")
16671732
@Test
16681733
public void setTagsACFail() {

sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobAsyncApiTests.java

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,8 @@ public void uploadInputStreamBadLength(long badLength, Class<? extends Throwable
279279
.verifyError(exception);
280280
} catch (IllegalArgumentException e) {
281281
//StepVerifier cant handle the error in the creation of BlobParallelUploadOptions
282-
assertEquals(e.getMessage(),
283-
"The value of the parameter 'length' should be between 0 and 9223372036854775807.");
282+
assertEquals("The value of the parameter 'length' should be between 0 and 9223372036854775807.",
283+
e.getMessage());
284284
}
285285
}
286286

@@ -1347,7 +1347,7 @@ public void setHTTPHeadersNull() {
13471347
}
13481348

13491349
@Test
1350-
public void setHTTPHeadersMin() throws NoSuchAlgorithmException {
1350+
public void setHTTPHeadersMin() {
13511351
Mono<BlobProperties> response = bc.getProperties().flatMap(properties -> {
13521352
BlobHttpHeaders headers;
13531353
try {
@@ -1621,6 +1621,75 @@ private static Stream<Arguments> setTagsACSupplier() {
16211621
return Stream.of(Arguments.of((String) null), Arguments.of("\"foo\" = 'bar'"));
16221622
}
16231623

1624+
@RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-02-06")
1625+
@ParameterizedTest
1626+
@MethodSource("com.azure.storage.blob.BlobTestBase#allConditionsSupplier")
1627+
public void setGetTagOptionsAC(OffsetDateTime modified, OffsetDateTime unmodified, String match, String noneMatch,
1628+
String leaseID) {
1629+
Map<String, String> t = new HashMap<>();
1630+
1631+
t.put("foo", "bar");
1632+
1633+
Mono<Response<Map<String, String>>> response = Mono
1634+
.zip(setupBlobLeaseCondition(bc, leaseID), setupBlobMatchCondition(bc, match), BlobTestBase::convertNulls)
1635+
.flatMap(conditions -> {
1636+
BlobRequestConditions bac = new BlobRequestConditions().setLeaseId(conditions.get(0))
1637+
.setIfMatch(conditions.get(1))
1638+
.setIfNoneMatch(noneMatch)
1639+
.setIfModifiedSince(modified)
1640+
.setIfUnmodifiedSince(unmodified);
1641+
return bc.setTagsWithResponse(new BlobSetTagsOptions(t).setRequestConditions(bac))
1642+
.then(bc.getTagsWithResponse(new BlobGetTagsOptions().setRequestConditions(bac)));
1643+
});
1644+
1645+
StepVerifier.create(response).assertNext(r -> {
1646+
assertResponseStatusCode(r, 200);
1647+
assertEquals(t, r.getValue());
1648+
}).verifyComplete();
1649+
}
1650+
1651+
@RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-02-06")
1652+
@ParameterizedTest
1653+
@MethodSource("com.azure.storage.blob.BlobTestBase#allConditionsFailSupplier")
1654+
public void setTagOptionsACFail(OffsetDateTime modified, OffsetDateTime unmodified, String match, String noneMatch,
1655+
String leaseID, String tags) {
1656+
Map<String, String> t = new HashMap<>();
1657+
1658+
//The x-ms-if-tags-request header is not supported
1659+
t.put("notfoo", "notbar");
1660+
1661+
Mono<Response<Void>> response = setupBlobMatchCondition(bc, noneMatch).flatMap(condition -> {
1662+
BlobRequestConditions bac = new BlobRequestConditions().setLeaseId(leaseID)
1663+
.setIfMatch(match)
1664+
.setIfNoneMatch(convertNull(condition))
1665+
.setIfModifiedSince(modified)
1666+
.setIfUnmodifiedSince(unmodified)
1667+
.setTagsConditions(tags);
1668+
return bc.setTagsWithResponse(new BlobSetTagsOptions(t).setRequestConditions(bac));
1669+
});
1670+
1671+
StepVerifier.create(response).verifyError(BlobStorageException.class);
1672+
}
1673+
1674+
@RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2026-02-06")
1675+
@ParameterizedTest
1676+
@MethodSource("com.azure.storage.blob.BlobTestBase#allConditionsFailSupplier")
1677+
public void getTagOptionsACFail(OffsetDateTime modified, OffsetDateTime unmodified, String match, String noneMatch,
1678+
String leaseID, String tags) {
1679+
//The x-ms-if-tags-request header is not supported
1680+
Mono<Response<Map<String, String>>> response = setupBlobMatchCondition(bc, noneMatch).flatMap(condition -> {
1681+
BlobRequestConditions bac = new BlobRequestConditions().setLeaseId(leaseID)
1682+
.setIfMatch(match)
1683+
.setIfNoneMatch(convertNull(condition))
1684+
.setIfModifiedSince(modified)
1685+
.setIfUnmodifiedSince(unmodified)
1686+
.setTagsConditions(tags);
1687+
return bc.getTagsWithResponse(new BlobGetTagsOptions().setRequestConditions(bac));
1688+
});
1689+
1690+
StepVerifier.create(response).verifyError(BlobStorageException.class);
1691+
}
1692+
16241693
@RequiredServiceVersion(clazz = BlobServiceVersion.class, min = "2019-07-07")
16251694
@Test
16261695
public void setTagsACFail() {
@@ -2751,7 +2820,7 @@ public void getNonEncodedSpecializedBlob() {
27512820
specializedBlobClientBuilder.containerName(ccAsync.getBlobContainerName()).blobName(originalBlobName);
27522821

27532822
BlockBlobAsyncClient blockBlobClient = specializedBlobClientBuilder.buildBlockBlobAsyncClient();
2754-
assertEquals(blockBlobClient.getBlobName(), originalBlobName);
2823+
assertEquals(originalBlobName, blockBlobClient.getBlobName());
27552824

27562825
// see if the blob name will be properly encoded in the url
27572826
String encodedName = Utility.urlEncode(originalBlobName);
@@ -2765,7 +2834,7 @@ public void getNonEncodedBlobClient() {
27652834
blobClientBuilder.containerName(ccAsync.getBlobContainerName()).blobName(originalBlobName);
27662835

27672836
BlobAsyncClient blobClient = blobClientBuilder.buildAsyncClient();
2768-
assertEquals(blobClient.getBlobName(), originalBlobName);
2837+
assertEquals(originalBlobName, blobClient.getBlobName());
27692838

27702839
// see if the blob name will be properly encoded in the url
27712840
String encodedName = Utility.urlEncode(originalBlobName);

sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/BlobTestBase.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,8 @@ public void beforeTest() {
199199
interceptorManager.addMatchers(Collections.singletonList(new CustomMatcher().setComparingBodies(false)
200200
.setHeadersKeyOnlyMatch(Arrays.asList("x-ms-lease-id", "x-ms-proposed-lease-id", "If-Modified-Since",
201201
"If-Unmodified-Since", "x-ms-expiry-time", "x-ms-source-if-modified-since",
202-
"x-ms-source-if-unmodified-since", "x-ms-source-lease-id", "x-ms-encryption-key-sha256"))
202+
"x-ms-source-if-unmodified-since", "x-ms-source-lease-id", "x-ms-encryption-key-sha256",
203+
"x-ms-blob-if-modified-since", "x-ms-blob-if-unmodified-since"))
203204
.setQueryOrderingIgnored(true)
204205
.setIgnoredQueryParameters(Collections.singletonList("sv"))));
205206

sdk/storage/azure-storage-blob/swagger/README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ autorest
1616
### Code generation settings
1717
``` yaml
1818
use: '@autorest/[email protected]'
19-
input-file: https://raw.githubusercontent.com/seanmcc-msft/azure-rest-api-specs/883244cd9a0b2fd0e43f1056e6c3a5824fa2c240/specification/storage/data-plane/Microsoft.BlobStorage/stable/2026-02-06/blob.json
19+
input-file: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/refs/heads/feature/storage/stg100base/specification/storage/data-plane/Microsoft.BlobStorage/stable/2026-02-06/blob.json
2020
java: true
2121
output-folder: ../
2222
namespace: com.azure.storage.blob
@@ -473,6 +473,13 @@ directive:
473473
delete $.IfNoneMatch["x-ms-parameter-grouping"];
474474
delete $.IfUnmodifiedSince["x-ms-parameter-grouping"];
475475
delete $.IfTags["x-ms-parameter-grouping"];
476+
- from: swagger-document
477+
where: $.parameters
478+
transform: >
479+
delete $.IfBlobMatch["x-ms-parameter-grouping"];
480+
delete $.IfBlobModifiedSince["x-ms-parameter-grouping"];
481+
delete $.IfBlobNoneMatch["x-ms-parameter-grouping"];
482+
delete $.IfBlobUnmodifiedSince["x-ms-parameter-grouping"];
476483
- from: swagger-document
477484
where: $.parameters
478485
transform: >

0 commit comments

Comments
 (0)