Skip to content

Commit 88e0c71

Browse files
committed
Add content-type in the AsyncRequestBody and corresponding tests.
1 parent be81185 commit 88e0c71

File tree

9 files changed

+109
-5
lines changed

9 files changed

+109
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"category": "AWS SDK for Java v2",
3+
"contributor": "",
4+
"type": "bugfix",
5+
"description": "Add support for content-type in AsyncRequestBody."
6+
}

core/auth/src/main/java/software/amazon/awssdk/auth/signer/internal/BaseEventStreamAsyncAws4Signer.java

+5
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,11 @@ public void subscribe(Subscriber<? super ByteBuffer> s) {
268268
public Optional<Long> contentLength() {
269269
return transformedRequestBody.contentLength();
270270
}
271+
272+
@Override
273+
public String contentType() {
274+
return transformedRequestBody.contentType();
275+
}
271276
}
272277

273278
static String toDebugString(Message m, boolean truncatePayload) {

core/sdk-core/src/main/java/software/amazon/awssdk/core/async/AsyncRequestBody.java

+11-3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import software.amazon.awssdk.annotations.SdkPublicApi;
2727
import software.amazon.awssdk.core.internal.async.ByteArrayAsyncRequestBody;
2828
import software.amazon.awssdk.core.internal.async.FileAsyncRequestBody;
29+
import software.amazon.awssdk.core.internal.util.Mimetype;
2930
import software.amazon.awssdk.utils.BinaryUtils;
3031

3132
/**
@@ -57,6 +58,13 @@ public interface AsyncRequestBody extends SdkPublisher<ByteBuffer> {
5758
*/
5859
Optional<Long> contentLength();
5960

61+
/**
62+
* @return The content type of the data being produced.
63+
*/
64+
default String contentType() {
65+
return Mimetype.MIMETYPE_OCTET_STREAM;
66+
}
67+
6068
/**
6169
* Creates an {@link AsyncRequestBody} the produces data from the input ByteBuffer publisher.
6270
* The data is delivered when the publisher publishes the data.
@@ -115,7 +123,7 @@ static AsyncRequestBody fromFile(File file) {
115123
* @see ByteArrayAsyncRequestBody
116124
*/
117125
static AsyncRequestBody fromString(String string, Charset cs) {
118-
return new ByteArrayAsyncRequestBody(string.getBytes(cs));
126+
return new ByteArrayAsyncRequestBody(string.getBytes(cs), Mimetype.MIMETYPE_TEXT_PLAIN);
119127
}
120128

121129
/**
@@ -137,7 +145,7 @@ static AsyncRequestBody fromString(String string) {
137145
* @return AsyncRequestBody instance.
138146
*/
139147
static AsyncRequestBody fromBytes(byte[] bytes) {
140-
return new ByteArrayAsyncRequestBody(bytes);
148+
return new ByteArrayAsyncRequestBody(bytes, Mimetype.MIMETYPE_OCTET_STREAM);
141149
}
142150

143151
/**
@@ -148,7 +156,7 @@ static AsyncRequestBody fromBytes(byte[] bytes) {
148156
* @return AsyncRequestBody instance.
149157
*/
150158
static AsyncRequestBody fromByteBuffer(ByteBuffer byteBuffer) {
151-
return new ByteArrayAsyncRequestBody(BinaryUtils.copyAllBytesFrom(byteBuffer));
159+
return fromBytes(BinaryUtils.copyAllBytesFrom(byteBuffer));
152160
}
153161

154162
/**

core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/ByteArrayAsyncRequestBody.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,23 @@ public final class ByteArrayAsyncRequestBody implements AsyncRequestBody {
3535

3636
private final byte[] bytes;
3737

38-
public ByteArrayAsyncRequestBody(byte[] bytes) {
38+
private final String mimetype;
39+
40+
public ByteArrayAsyncRequestBody(byte[] bytes, String mimetype) {
3941
this.bytes = bytes.clone();
42+
this.mimetype = mimetype;
4043
}
4144

4245
@Override
4346
public Optional<Long> contentLength() {
4447
return Optional.of((long) bytes.length);
4548
}
4649

50+
@Override
51+
public String contentType() {
52+
return mimetype;
53+
}
54+
4755
@Override
4856
public void subscribe(Subscriber<? super ByteBuffer> s) {
4957
// As per rule 1.9 we must throw NullPointerException if the subscriber parameter is null

core/sdk-core/src/main/java/software/amazon/awssdk/core/internal/async/FileAsyncRequestBody.java

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.reactivestreams.Subscription;
3030
import software.amazon.awssdk.annotations.SdkInternalApi;
3131
import software.amazon.awssdk.core.async.AsyncRequestBody;
32+
import software.amazon.awssdk.core.internal.util.Mimetype;
3233
import software.amazon.awssdk.core.internal.util.NoopSubscription;
3334
import software.amazon.awssdk.utils.builder.SdkBuilder;
3435

@@ -70,6 +71,11 @@ public Optional<Long> contentLength() {
7071
}
7172
}
7273

74+
@Override
75+
public String contentType() {
76+
return Mimetype.getInstance().getMimetype(path);
77+
}
78+
7379
@Override
7480
public void subscribe(Subscriber<? super ByteBuffer> s) {
7581
try {

core/sdk-core/src/main/java/software/amazon/awssdk/core/runtime/transform/AsyncStreamingRequestMarshaller.java

+7
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@
1515

1616
package software.amazon.awssdk.core.runtime.transform;
1717

18+
import static software.amazon.awssdk.http.Header.CONTENT_TYPE;
19+
1820
import software.amazon.awssdk.annotations.SdkProtectedApi;
1921
import software.amazon.awssdk.core.async.AsyncRequestBody;
2022
import software.amazon.awssdk.core.internal.transform.AbstractStreamingRequestMarshaller;
2123
import software.amazon.awssdk.http.SdkHttpFullRequest;
24+
import software.amazon.awssdk.utils.StringUtils;
2225

2326
/**
2427
* Augments a {@link Marshaller} to add contents for an async streamed request.
@@ -42,6 +45,10 @@ public static Builder builder() {
4245
@Override
4346
public SdkHttpFullRequest marshall(T in) {
4447
SdkHttpFullRequest.Builder marshalled = delegateMarshaller.marshall(in).toBuilder();
48+
String contentType = marshalled.firstMatchingHeader(CONTENT_TYPE).orElse(null);
49+
if (StringUtils.isEmpty(contentType)) {
50+
marshalled.putHeader(CONTENT_TYPE, asyncRequestBody.contentType());
51+
}
4552

4653
addHeaders(marshalled, asyncRequestBody.contentLength(), requiresLength, transferEncoding, useHttp2);
4754

core/sdk-core/src/test/java/software/amazon/awssdk/core/async/AsyncRequestBodyTest.java

+57
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,39 @@
1515

1616
package software.amazon.awssdk.core.async;
1717

18+
import static java.nio.charset.StandardCharsets.UTF_8;
1819
import static org.assertj.core.api.Assertions.assertThat;
1920

2021
import com.google.common.jimfs.Configuration;
2122
import com.google.common.jimfs.Jimfs;
2223
import io.reactivex.Flowable;
24+
import java.io.File;
25+
import java.io.FileWriter;
2326
import java.io.IOException;
27+
import java.io.InputStream;
2428
import java.nio.ByteBuffer;
2529
import java.nio.charset.StandardCharsets;
2630
import java.nio.file.FileSystem;
2731
import java.nio.file.Files;
2832
import java.nio.file.Path;
33+
import java.time.Instant;
34+
import java.util.Collections;
35+
import java.util.List;
36+
import java.util.concurrent.Callable;
2937
import java.util.concurrent.CountDownLatch;
38+
import java.util.stream.Collectors;
39+
import org.assertj.core.util.Lists;
40+
import org.junit.Rule;
3041
import org.junit.Test;
42+
import org.junit.rules.TemporaryFolder;
3143
import org.junit.runner.RunWith;
3244
import org.junit.runners.Parameterized;
45+
import org.reactivestreams.Publisher;
3346
import org.reactivestreams.Subscriber;
47+
import software.amazon.awssdk.core.internal.util.Mimetype;
3448
import software.amazon.awssdk.http.async.SimpleSubscriber;
3549
import software.amazon.awssdk.utils.BinaryUtils;
50+
import software.amazon.awssdk.utils.StringInputStream;
3651

3752
@RunWith(Parameterized.class)
3853
public class AsyncRequestBodyTest {
@@ -96,6 +111,48 @@ public void onComplete() {
96111
assertThat(sb.toString()).isEqualTo(testString);
97112
}
98113

114+
@Test
115+
public void stringConstructorHasCorrectContentType() {
116+
AsyncRequestBody requestBody = AsyncRequestBody.fromString("hello world");
117+
assertThat(requestBody.contentType()).isEqualTo(Mimetype.MIMETYPE_TEXT_PLAIN);
118+
}
119+
120+
@Test
121+
public void fileConstructorHasCorrectContentType() {
122+
AsyncRequestBody requestBody = AsyncRequestBody.fromFile(path);
123+
assertThat(requestBody.contentType()).isEqualTo(Mimetype.MIMETYPE_OCTET_STREAM);
124+
}
125+
126+
@Test
127+
public void bytesArrayConstructorHasCorrectContentType() {
128+
AsyncRequestBody requestBody = AsyncRequestBody.fromBytes("hello world".getBytes());
129+
assertThat(requestBody.contentType()).isEqualTo(Mimetype.MIMETYPE_OCTET_STREAM);
130+
}
131+
132+
@Test
133+
public void bytesBufferConstructorHasCorrectContentType() {
134+
ByteBuffer byteBuffer = ByteBuffer.wrap("hello world".getBytes());
135+
AsyncRequestBody requestBody = AsyncRequestBody.fromByteBuffer(byteBuffer);
136+
assertThat(requestBody.contentType()).isEqualTo(Mimetype.MIMETYPE_OCTET_STREAM);
137+
}
138+
139+
@Test
140+
public void emptyBytesConstructorHasCorrectContentType() {
141+
AsyncRequestBody requestBody = AsyncRequestBody.empty();
142+
assertThat(requestBody.contentType()).isEqualTo(Mimetype.MIMETYPE_OCTET_STREAM);
143+
}
144+
145+
@Test
146+
public void publisherConstructorHasCorrectContentType() {
147+
List<String> requestBodyStrings = Lists.newArrayList("A", "B", "C");
148+
List<ByteBuffer> bodyBytes = requestBodyStrings.stream()
149+
.map(s -> ByteBuffer.wrap(s.getBytes(StandardCharsets.UTF_8)))
150+
.collect(Collectors.toList());
151+
Publisher<ByteBuffer> bodyPublisher = Flowable.fromIterable(bodyBytes);
152+
AsyncRequestBody requestBody = AsyncRequestBody.fromPublisher(bodyPublisher);
153+
assertThat(requestBody.contentType()).isEqualTo(Mimetype.MIMETYPE_OCTET_STREAM);
154+
}
155+
99156
@Test
100157
public void fromBytes_byteArrayNotNull_createsCopy() {
101158
byte[] original = {0x1, 0x2, 0x3, 0x4};

core/sdk-core/src/test/java/software/amazon/awssdk/core/internal/async/ByteArrayAsyncRequestBodyTest.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.junit.Test;
2222
import org.reactivestreams.Subscriber;
2323
import org.reactivestreams.Subscription;
24+
import software.amazon.awssdk.core.internal.util.Mimetype;
2425

2526
public class ByteArrayAsyncRequestBodyTest {
2627
private class testSubscriber implements Subscriber<ByteBuffer> {
@@ -54,7 +55,8 @@ public void onComplete() {
5455

5556
@Test
5657
public void concurrentRequests_shouldCompleteNormally() {
57-
ByteArrayAsyncRequestBody byteArrayReq = new ByteArrayAsyncRequestBody("Hello World!".getBytes());
58+
ByteArrayAsyncRequestBody byteArrayReq = new ByteArrayAsyncRequestBody("Hello World!".getBytes(),
59+
Mimetype.MIMETYPE_OCTET_STREAM);
5860
byteArrayReq.subscribe(subscriber);
5961
assertTrue(subscriber.onCompleteCalled.get());
6062
}

services/s3/src/main/java/software/amazon/awssdk/services/s3/checksums/ChecksumCalculatingAsyncRequestBody.java

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ public Optional<Long> contentLength() {
4040
return wrapped.contentLength();
4141
}
4242

43+
@Override
44+
public String contentType() {
45+
return wrapped.contentType();
46+
}
47+
4348
@Override
4449
public void subscribe(Subscriber<? super ByteBuffer> s) {
4550
sdkChecksum.reset();

0 commit comments

Comments
 (0)