kopia lustrzana https://github.com/gaul/s3proxy
Add If-Match and If-None-Match support for PutObject operations
rodzic
5eec0f23fc
commit
07d420ef63
|
@ -1994,6 +1994,51 @@ public class S3ProxyHandler {
|
|||
throw new S3Exception(S3ErrorCode.ENTITY_TOO_LARGE);
|
||||
}
|
||||
|
||||
// Handle If-Match and If-None-Match headers for PUT operations.
|
||||
// Unlike GET operations which use GetOptions to pass these conditions
|
||||
// to jclouds, PUT operations lack a PutOptions equivalent in jclouds.
|
||||
// Therefore, we manually fetch the blob metadata and validate ETags.
|
||||
String ifMatch = request.getHeader(HttpHeaders.IF_MATCH);
|
||||
String ifNoneMatch = request.getHeader(HttpHeaders.IF_NONE_MATCH);
|
||||
|
||||
if (ifMatch != null || ifNoneMatch != null) {
|
||||
BlobMetadata metadata = blobStore.blobMetadata(containerName,
|
||||
blobName);
|
||||
|
||||
if (ifMatch != null) {
|
||||
if (metadata == null) {
|
||||
throw new S3Exception(S3ErrorCode.NO_SUCH_KEY);
|
||||
}
|
||||
String eTag = metadata.getETag();
|
||||
if (eTag != null) {
|
||||
eTag = maybeQuoteETag(eTag);
|
||||
if (!equalsIgnoringSurroundingQuotes(ifMatch, eTag)) {
|
||||
throw new S3Exception(S3ErrorCode.PRECONDITION_FAILED);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new S3Exception(S3ErrorCode.PRECONDITION_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
if (ifNoneMatch != null) {
|
||||
if (ifNoneMatch.equals("*")) {
|
||||
if (metadata != null) {
|
||||
throw new S3Exception(S3ErrorCode.PRECONDITION_FAILED);
|
||||
}
|
||||
}
|
||||
else if (metadata != null) {
|
||||
String eTag = metadata.getETag();
|
||||
if (eTag != null) {
|
||||
eTag = maybeQuoteETag(eTag);
|
||||
if (equalsIgnoringSurroundingQuotes(ifNoneMatch, eTag)) {
|
||||
throw new S3Exception(S3ErrorCode.PRECONDITION_FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BlobAccess access;
|
||||
String cannedAcl = request.getHeader(AwsHttpHeaders.ACL);
|
||||
if (cannedAcl == null || cannedAcl.equalsIgnoreCase("private")) {
|
||||
|
|
|
@ -1791,6 +1791,85 @@ public final class AwsSdkTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutIfMatch() throws Exception {
|
||||
String blobName = "test-blob";
|
||||
|
||||
var metadata = new ObjectMetadata();
|
||||
metadata.setContentLength(BYTE_SOURCE.size());
|
||||
PutObjectResult result = client.putObject(containerName, blobName,
|
||||
BYTE_SOURCE.openStream(), metadata);
|
||||
String eTag = result.getETag();
|
||||
|
||||
// PUT with matching If-Match should succeed
|
||||
metadata.setContentLength(BYTE_SOURCE.size());
|
||||
var request = new PutObjectRequest(containerName, blobName,
|
||||
BYTE_SOURCE.openStream(), metadata);
|
||||
request.setIfMatch(eTag);
|
||||
client.putObject(request);
|
||||
|
||||
// PUT with non-matching If-Match should fail
|
||||
metadata.setContentLength(BYTE_SOURCE.size());
|
||||
var badRequest = new PutObjectRequest(containerName, blobName,
|
||||
BYTE_SOURCE.openStream(), metadata);
|
||||
badRequest.setIfMatch("wrong-etag");
|
||||
try {
|
||||
client.putObject(badRequest);
|
||||
Fail.failBecauseExceptionWasNotThrown(AmazonS3Exception.class);
|
||||
} catch (AmazonS3Exception e) {
|
||||
assertThat(e.getStatusCode()).isEqualTo(412);
|
||||
}
|
||||
|
||||
// PUT with If-Match on non-existent object should fail with 404
|
||||
metadata.setContentLength(BYTE_SOURCE.size());
|
||||
var nonExistentRequest = new PutObjectRequest(containerName,
|
||||
"non-existent", BYTE_SOURCE.openStream(), metadata);
|
||||
nonExistentRequest.setIfMatch(eTag);
|
||||
try {
|
||||
client.putObject(nonExistentRequest);
|
||||
Fail.failBecauseExceptionWasNotThrown(AmazonS3Exception.class);
|
||||
} catch (AmazonS3Exception e) {
|
||||
assertThat(e.getStatusCode()).isEqualTo(404);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPutIfNoneMatch() throws Exception {
|
||||
String blobName = "test-blob";
|
||||
|
||||
var metadata = new ObjectMetadata();
|
||||
metadata.setContentLength(BYTE_SOURCE.size());
|
||||
PutObjectResult result = client.putObject(containerName, blobName,
|
||||
BYTE_SOURCE.openStream(), metadata);
|
||||
String eTag = result.getETag();
|
||||
|
||||
// PUT with If-None-Match matching current ETag should fail
|
||||
metadata.setContentLength(BYTE_SOURCE.size());
|
||||
var request = new PutObjectRequest(containerName, blobName,
|
||||
BYTE_SOURCE.openStream(), metadata);
|
||||
request.setIfNoneMatch(eTag);
|
||||
try {
|
||||
client.putObject(request);
|
||||
Fail.failBecauseExceptionWasNotThrown(AmazonS3Exception.class);
|
||||
} catch (AmazonS3Exception e) {
|
||||
assertThat(e.getStatusCode()).isEqualTo(412);
|
||||
}
|
||||
|
||||
// PUT with If-None-Match with different ETag should succeed
|
||||
metadata.setContentLength(BYTE_SOURCE.size());
|
||||
var goodRequest = new PutObjectRequest(containerName, blobName,
|
||||
BYTE_SOURCE.openStream(), metadata);
|
||||
goodRequest.setIfNoneMatch("different-etag");
|
||||
client.putObject(goodRequest);
|
||||
|
||||
// PUT with If-None-Match on non-existent object should succeed
|
||||
metadata.setContentLength(BYTE_SOURCE.size());
|
||||
var nonExistentRequest = new PutObjectRequest(containerName,
|
||||
"non-existent", BYTE_SOURCE.openStream(), metadata);
|
||||
nonExistentRequest.setIfNoneMatch("*");
|
||||
client.putObject(nonExistentRequest);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListRelativePath() throws Exception {
|
||||
assumeTrue(!blobStoreType.equals("filesystem"));
|
||||
|
|
Ładowanie…
Reference in New Issue