Skip to content

Commit 84d9780

Browse files
authored
Fixed the issue where the position of the ByteBuffer from the request… (#4212)
* Fixed the issue where the position of the ByteBuffer from the request is not honored in NettyNioAsyncHttpClient. * Add assertion
1 parent 585c4d8 commit 84d9780

File tree

4 files changed

+43
-8
lines changed

4 files changed

+43
-8
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"type": "bugfix",
3+
"category": "Netty NIO HTTP Client",
4+
"contributor": "",
5+
"description": "Fixed the issue where the position of the ByteBuffer from the request is not honored in NettyNioAsyncHttpClient."
6+
}

http-clients/netty-nio-client/src/main/java/software/amazon/awssdk/http/nio/netty/internal/NettyRequestExecutor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ public void onNext(ByteBuffer contentBytes) {
445445

446446
try {
447447
int newLimit = clampedBufferLimit(contentBytes.remaining());
448-
contentBytes.limit(newLimit);
448+
contentBytes.limit(contentBytes.position() + newLimit);
449449
ByteBuf contentByteBuf = Unpooled.wrappedBuffer(contentBytes);
450450
HttpContent content = new DefaultHttpContent(contentByteBuf);
451451

http-clients/netty-nio-client/src/test/java/software/amazon/awssdk/http/nio/netty/NettyNioAsyncHttpClientWireMockTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,17 @@
1818
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
1919
import static com.github.tomakehurst.wiremock.client.WireMock.any;
2020
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
21+
import static com.github.tomakehurst.wiremock.client.WireMock.post;
2122
import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
2223
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
2324
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
2425
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
2526
import static com.github.tomakehurst.wiremock.client.WireMock.verify;
2627
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
28+
import static java.util.Collections.emptyMap;
2729
import static java.util.Collections.singletonMap;
2830
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
31+
import static org.apache.commons.lang3.RandomStringUtils.randomAscii;
2932
import static org.apache.commons.lang3.StringUtils.reverse;
3033
import static org.assertj.core.api.Assertions.assertThat;
3134
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -41,6 +44,7 @@
4144
import static software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClientTestUtils.makeSimpleRequest;
4245

4346
import com.github.tomakehurst.wiremock.WireMockServer;
47+
import com.github.tomakehurst.wiremock.client.WireMock;
4448
import com.github.tomakehurst.wiremock.http.Fault;
4549
import com.github.tomakehurst.wiremock.junit.WireMockRule;
4650
import io.netty.channel.Channel;
@@ -55,6 +59,7 @@
5559
import io.netty.util.AttributeKey;
5660
import java.io.IOException;
5761
import java.net.URI;
62+
import java.nio.ByteBuffer;
5863
import java.time.Duration;
5964
import java.util.ArrayList;
6065
import java.util.Collections;
@@ -80,6 +85,7 @@
8085
import software.amazon.awssdk.http.SdkHttpFullRequest;
8186
import software.amazon.awssdk.http.SdkHttpMethod;
8287
import software.amazon.awssdk.http.SdkHttpRequest;
88+
import software.amazon.awssdk.http.SimpleHttpContentPublisher;
8389
import software.amazon.awssdk.http.async.AsyncExecuteRequest;
8490
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
8591
import software.amazon.awssdk.http.nio.netty.internal.NettyConfiguration;
@@ -558,6 +564,25 @@ public ChannelFuture close() {
558564
assertThat(channelClosedFuture.get(5, TimeUnit.SECONDS)).isTrue();
559565
}
560566

567+
@Test
568+
public void execute_requestByteBufferWithNonZeroPosition_shouldHonor() throws Exception {
569+
String body = randomAlphabetic(70);
570+
byte[] content = randomAscii(100).getBytes();
571+
ByteBuffer requestContent = ByteBuffer.wrap(content);
572+
requestContent.position(95);
573+
String expected = new String(content, 95, 5);
574+
575+
URI uri = URI.create("http://localhost:" + mockServer.port());
576+
stubFor(post(urlPathEqualTo("/"))
577+
.withRequestBody(equalTo(expected)).willReturn(aResponse().withBody(body)));
578+
SdkHttpRequest request = createRequest(uri, "/", expected, SdkHttpMethod.POST, emptyMap());
579+
RecordingResponseHandler recorder = new RecordingResponseHandler();
580+
581+
client.execute(AsyncExecuteRequest.builder().request(request).requestContentPublisher(new SimpleHttpContentPublisher(requestContent)).responseHandler(recorder).build());
582+
recorder.completeFuture.get(5, TimeUnit.SECONDS);
583+
verify(postRequestedFor(urlPathEqualTo("/")).withRequestBody(equalTo(expected)));
584+
}
585+
561586
// Needs to be a non-anon class in order to spy
562587
public static class CustomThreadFactory implements ThreadFactory {
563588
@Override

test/http-client-tests/src/main/java/software/amazon/awssdk/http/SimpleHttpContentPublisher.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,24 @@
3232
@SdkInternalApi
3333
public final class SimpleHttpContentPublisher implements SdkHttpContentPublisher {
3434

35-
private final byte[] content;
35+
private final ByteBuffer content;
3636
private final int length;
3737

3838
public SimpleHttpContentPublisher(SdkHttpFullRequest request) {
39-
this.content = request.contentStreamProvider().map(p -> invokeSafely(() -> IoUtils.toByteArray(p.newStream())))
40-
.orElseGet(() -> new byte[0]);
41-
this.length = content.length;
39+
this.content =
40+
request.contentStreamProvider().map(p -> invokeSafely(() -> ByteBuffer.wrap(IoUtils.toByteArray(p.newStream()))))
41+
.orElseGet(() -> ByteBuffer.wrap(new byte[0]));
42+
this.length = content.remaining();
4243
}
4344

4445
public SimpleHttpContentPublisher(byte[] body) {
45-
this.content = body;
46-
this.length = body.length;
46+
this(ByteBuffer.wrap(body));
4747
}
4848

49+
public SimpleHttpContentPublisher(ByteBuffer byteBuffer) {
50+
this.content = byteBuffer;
51+
this.length = byteBuffer.remaining();
52+
}
4953

5054
@Override
5155
public Optional<Long> contentLength() {
@@ -72,7 +76,7 @@ public void request(long n) {
7276
if (n <= 0) {
7377
s.onError(new IllegalArgumentException("Demand must be positive"));
7478
} else {
75-
s.onNext(ByteBuffer.wrap(content));
79+
s.onNext(content);
7680
s.onComplete();
7781
}
7882
}

0 commit comments

Comments
 (0)