@@ -18,13 +18,17 @@ package com.adobe.testing.s3mock.its
1818import com.adobe.testing.s3mock.dto.InitiateMultipartUploadResult
1919import com.adobe.testing.s3mock.util.DigestUtil
2020import org.apache.http.HttpHeaders
21+ import org.apache.http.HttpHeaders.CONTENT_TYPE
2122import org.apache.http.HttpStatus
2223import org.apache.http.client.methods.HttpDelete
2324import org.apache.http.client.methods.HttpGet
2425import org.apache.http.client.methods.HttpPost
2526import org.apache.http.client.methods.HttpPut
27+ import org.apache.http.entity.ByteArrayEntity
28+ import org.apache.http.entity.ContentType
2629import org.apache.http.entity.FileEntity
2730import org.apache.http.entity.StringEntity
31+ import org.apache.http.entity.mime.MultipartEntityBuilder
2832import org.apache.http.impl.client.CloseableHttpClient
2933import org.apache.http.message.BasicHeader
3034import org.assertj.core.api.Assertions.assertThat
@@ -34,6 +38,8 @@ import software.amazon.awssdk.core.sync.RequestBody
3438import software.amazon.awssdk.services.s3.S3Client
3539import software.amazon.awssdk.services.s3.model.CompletedPart
3640import software.amazon.awssdk.services.s3.presigner.S3Presigner
41+ import tel.schich.awss3postobjectpresigner.S3PostObjectPresigner
42+ import tel.schich.awss3postobjectpresigner.S3PostObjectRequest
3743import java.io.File
3844import java.nio.file.Files
3945import java.nio.file.Path
@@ -44,6 +50,62 @@ internal class PresignedUrlIT : S3TestBase() {
4450 private val httpClient: CloseableHttpClient = createHttpClient()
4551 private val s3Client: S3Client = createS3Client()
4652 private val s3Presigner: S3Presigner = createS3Presigner()
53+ private val s3PostObjectPresigner: S3PostObjectPresigner = createS3PostObjectPresigner()
54+
55+ @Test
56+ @S3VerifiedFailure(year = 2025 ,
57+ reason = " S3PostObjectPresigner does not create working presigned URLs." )
58+ fun testPresignedUrl_postObject_largeFile (testInfo : TestInfo ) {
59+ val key = randomName
60+ val bucketName = givenBucket(testInfo)
61+
62+ val presignedUrlString = s3PostObjectPresigner.presignPost(
63+ S3PostObjectRequest
64+ .builder()
65+ .bucket(bucketName)
66+ .expiration(Duration .ofMinutes(1L ))
67+ .build()
68+ ).uri().toString()
69+
70+ assertThat(presignedUrlString).isNotBlank()
71+
72+ val randomMBytes = randomMBytes(20 )
73+ HttpPost (presignedUrlString).apply {
74+ this .entity = MultipartEntityBuilder .create()
75+ .addTextBody(" key" , key)
76+ .addTextBody(CONTENT_TYPE , " application/octet-stream" )
77+ // .addTextBody(X_AMZ_STORAGE_CLASS, "INTELLIGENT_TIERING")
78+ .addTextBody(" tagging" , " <Tagging><TagSet><Tag><Key>Tag Name</Key><Value>Tag Value</Value></Tag></TagSet></Tagging>" )
79+ .addBinaryBody(" file" , randomMBytes.inputStream(), ContentType .APPLICATION_OCTET_STREAM , key)
80+ .build()
81+ }.also { post ->
82+ httpClient.execute(
83+ post
84+ ).use {
85+ assertThat(it.statusLine.statusCode).isEqualTo(HttpStatus .SC_OK )
86+ val expectedEtag = " \" ${DigestUtil .hexDigest(randomMBytes.inputStream())} \" "
87+ val actualEtag = it.getFirstHeader(HttpHeaders .ETAG ).value
88+ assertThat(actualEtag).isEqualTo(expectedEtag)
89+ }
90+ }
91+
92+ s3Client.getObject {
93+ it.bucket(bucketName)
94+ it.key(key)
95+ }.use {
96+ val expectedEtag = " \" ${DigestUtil .hexDigest(randomMBytes.inputStream())} \" "
97+ val actualEtag = " \" ${DigestUtil .hexDigest(it)} \" "
98+ assertThat(actualEtag).isEqualTo(expectedEtag)
99+ }
100+ s3Client.getObjectTagging {
101+ it.bucket(bucketName)
102+ it.key(key)
103+ }.also {
104+ assertThat(it.tagSet()).hasSize(1 )
105+ assertThat(it.tagSet()[0 ].key()).isEqualTo(" Tag Name" )
106+ assertThat(it.tagSet()[0 ].value()).isEqualTo(" Tag Value" )
107+ }
108+ }
47109
48110 @Test
49111 @S3VerifiedSuccess(year = 2025 )
@@ -180,6 +242,43 @@ internal class PresignedUrlIT : S3TestBase() {
180242 }
181243 }
182244
245+ @Test
246+ @S3VerifiedSuccess(year = 2025 )
247+ fun testPresignedUrl_putObject_largeFile (testInfo : TestInfo ) {
248+ val key = randomName
249+ val bucketName = givenBucket(testInfo)
250+
251+ val presignedUrlString = s3Presigner.presignPutObject {
252+ it.putObjectRequest {
253+ it.bucket(bucketName)
254+ it.key(key)
255+ }
256+ it.signatureDuration(Duration .ofMinutes(1L ))
257+ }.url().toString()
258+
259+ assertThat(presignedUrlString).isNotBlank()
260+
261+ val randomMBytes = randomMBytes(20 )
262+ HttpPut (presignedUrlString).apply {
263+ this .entity = ByteArrayEntity (randomMBytes)
264+ }.also { put ->
265+ httpClient.execute(
266+ put
267+ ).use {
268+ assertThat(it.statusLine.statusCode).isEqualTo(HttpStatus .SC_OK )
269+ }
270+ }
271+
272+ s3Client.getObject {
273+ it.bucket(bucketName)
274+ it.key(key)
275+ }.use {
276+ val expectedEtag = " \" ${DigestUtil .hexDigest(randomMBytes.inputStream())} \" "
277+ val actualEtag = " \" ${DigestUtil .hexDigest(it)} \" "
278+ assertThat(actualEtag).isEqualTo(expectedEtag)
279+ }
280+ }
281+
183282 @Test
184283 @S3VerifiedSuccess(year = 2025 )
185284 fun testPresignedUrl_createMultipartUpload (testInfo : TestInfo ) {
0 commit comments