diff --git a/integration-tests/src/test/kotlin/com/adobe/testing/s3mock/its/GetPutDeleteObjectIT.kt b/integration-tests/src/test/kotlin/com/adobe/testing/s3mock/its/GetPutDeleteObjectIT.kt index 160eb45e0..d3b9fb1ba 100644 --- a/integration-tests/src/test/kotlin/com/adobe/testing/s3mock/its/GetPutDeleteObjectIT.kt +++ b/integration-tests/src/test/kotlin/com/adobe/testing/s3mock/its/GetPutDeleteObjectIT.kt @@ -1336,6 +1336,23 @@ internal class GetPutDeleteObjectIT : S3TestBase() { } } + @Test + @S3VerifiedSuccess(year = 2025) + fun `GET object succeeds with unquoted if-match header`(testInfo: TestInfo) { + val (bucketName, putObjectResponse) = givenBucketAndObject(testInfo, UPLOAD_FILE_NAME) + val matchingEtag = putObjectResponse.eTag() + val unquotedEtag = matchingEtag.substring(1,matchingEtag.length - 1) + + s3Client.getObject { + it.bucket(bucketName) + it.key(UPLOAD_FILE_NAME) + it.ifMatch(unquotedEtag) + }.use { + assertThat(it.response().eTag()).isEqualTo(matchingEtag) + assertThat(it.response().contentLength()).isEqualTo(UPLOAD_FILE_LENGTH) + } + } + @Test @S3VerifiedSuccess(year = 2025) fun `GET object succeeds with if-match=true and if-unmodified-since=false`(testInfo: TestInfo) { diff --git a/server/src/main/java/com/adobe/testing/s3mock/service/ObjectService.java b/server/src/main/java/com/adobe/testing/s3mock/service/ObjectService.java index 8d2dab691..83b8873a9 100644 --- a/server/src/main/java/com/adobe/testing/s3mock/service/ObjectService.java +++ b/server/src/main/java/com/adobe/testing/s3mock/service/ObjectService.java @@ -368,11 +368,13 @@ public void verifyObjectMatching( var setMatch = match != null && !match.isEmpty(); if (setMatch) { - if (match.contains(WILDCARD_ETAG) || match.contains(WILDCARD) || match.contains(etag)) { - // request cares only that the object exists or that the etag matches. + assert etag != null; + var unquotedEtag = etag.replace("\"", ""); + if (match.contains(WILDCARD_ETAG) || match.contains(WILDCARD) || match.contains(unquotedEtag) + || match.contains(etag)) { LOG.debug("Object {} exists", s3ObjectMetadata.key()); return; - } else if (!match.contains(etag)) { + } else if (!match.contains(unquotedEtag) && !match.contains(etag)) { LOG.debug("Object {} does not match etag {}", s3ObjectMetadata.key(), etag); throw PRECONDITION_FAILED; }