Skip to content

Commit e8193ae

Browse files
dgolombekDavid Golombek
and
David Golombek
authored
Extend Response to support returning ByteBufs (#1954)
NettyResponse is already dealing with ByteBufs under the hood, this lets the caller access them cleanly. This allows callers that are already using Netty to use AHC much more efficiently. Fixes #1953 Co-authored-by: David Golombek <[email protected]>
1 parent 6aee54c commit e8193ae

File tree

6 files changed

+52
-5
lines changed

6 files changed

+52
-5
lines changed

Diff for: client/src/main/java/org/asynchttpclient/HttpResponseBodyPart.java

+7
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.asynchttpclient;
1717

18+
import io.netty.buffer.ByteBuf;
1819
import java.nio.ByteBuffer;
1920

2021
/**
@@ -44,6 +45,12 @@ protected HttpResponseBodyPart(boolean last) {
4445
*/
4546
public abstract ByteBuffer getBodyByteBuffer();
4647

48+
/**
49+
* @return the {@link ByteBuf} of the bytes read from the response's chunk.
50+
* The {@link ByteBuf}'s capacity is equal to the number of bytes available.
51+
*/
52+
public abstract ByteBuf getBodyByteBuf();
53+
4754
/**
4855
* @return true if this is the last part.
4956
*/

Diff for: client/src/main/java/org/asynchttpclient/Response.java

+8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*/
1717
package org.asynchttpclient;
1818

19+
import io.netty.buffer.ByteBuf;
1920
import io.netty.handler.codec.http.HttpHeaders;
2021
import io.netty.handler.codec.http.cookie.Cookie;
2122
import org.asynchttpclient.netty.NettyResponse;
@@ -61,6 +62,13 @@ public interface Response {
6162
*/
6263
ByteBuffer getResponseBodyAsByteBuffer();
6364

65+
/**
66+
* Return the entire response body as a ByteBuf.
67+
*
68+
* @return the entire response body as a ByteBuf.
69+
*/
70+
ByteBuf getResponseBodyAsByteBuf();
71+
6472
/**
6573
* Returns an input stream for the response body. Note that you should not try to get this more than once, and that you should not close the stream.
6674
*

Diff for: client/src/main/java/org/asynchttpclient/netty/EagerResponseBodyPart.java

+6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import io.netty.buffer.ByteBuf;
1919
import io.netty.buffer.ByteBufUtil;
20+
import io.netty.buffer.Unpooled;
2021
import org.asynchttpclient.HttpResponseBodyPart;
2122

2223
import java.nio.ByteBuffer;
@@ -53,4 +54,9 @@ public int length() {
5354
public ByteBuffer getBodyByteBuffer() {
5455
return ByteBuffer.wrap(bytes);
5556
}
57+
58+
@Override
59+
public ByteBuf getBodyByteBuf() {
60+
return Unpooled.wrappedBuffer(bytes);
61+
}
5662
}

Diff for: client/src/main/java/org/asynchttpclient/netty/LazyResponseBodyPart.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ public LazyResponseBodyPart(ByteBuf buf, boolean last) {
3333
this.buf = buf;
3434
}
3535

36-
public ByteBuf getBuf() {
36+
@Override
37+
public ByteBuf getBodyByteBuf() {
3738
return buf;
3839
}
3940

Diff for: client/src/main/java/org/asynchttpclient/netty/NettyResponse.java

+12
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
*/
1616
package org.asynchttpclient.netty;
1717

18+
import io.netty.buffer.ByteBuf;
19+
import io.netty.buffer.ByteBufAllocator;
20+
import io.netty.buffer.CompositeByteBuf;
1821
import io.netty.handler.codec.http.EmptyHttpHeaders;
1922
import io.netty.handler.codec.http.HttpHeaders;
2023
import io.netty.handler.codec.http.cookie.ClientCookieDecoder;
@@ -192,6 +195,15 @@ public ByteBuffer getResponseBodyAsByteBuffer() {
192195
return target;
193196
}
194197

198+
@Override
199+
public ByteBuf getResponseBodyAsByteBuf() {
200+
CompositeByteBuf compositeByteBuf = ByteBufAllocator.DEFAULT.compositeBuffer(bodyParts.size());
201+
for (HttpResponseBodyPart part : bodyParts) {
202+
compositeByteBuf.addComponent(true, part.getBodyByteBuf());
203+
}
204+
return compositeByteBuf;
205+
}
206+
195207
@Override
196208
public String getResponseBody() {
197209
return getResponseBody(withDefault(extractContentTypeCharsetAttribute(getContentType()), UTF_8));

Diff for: client/src/test/java/org/asynchttpclient/netty/NettyAsyncResponseTest.java

+17-4
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,16 @@
1313
package org.asynchttpclient.netty;
1414

1515
import io.github.artsok.RepeatedIfExceptionsTest;
16+
import io.netty.buffer.ByteBuf;
17+
import io.netty.buffer.Unpooled;
1618
import io.netty.handler.codec.http.DefaultHttpHeaders;
1719
import io.netty.handler.codec.http.HttpHeaders;
1820
import io.netty.handler.codec.http.cookie.Cookie;
21+
import org.asynchttpclient.HttpResponseBodyPart;
1922

23+
import java.nio.charset.StandardCharsets;
2024
import java.text.SimpleDateFormat;
21-
import java.util.Date;
22-
import java.util.List;
23-
import java.util.Locale;
24-
import java.util.TimeZone;
25+
import java.util.*;
2526

2627
import static io.netty.handler.codec.http.HttpHeaderNames.SET_COOKIE;
2728
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -73,4 +74,16 @@ public void testCookieParseWeirdExpiresValue() {
7374
Cookie cookie = cookies.get(0);
7475
assertEquals(Long.MIN_VALUE, cookie.maxAge());
7576
}
77+
78+
@RepeatedIfExceptionsTest(repeats = 5)
79+
public void testGetResponseBodyAsByteBuffer() {
80+
List<HttpResponseBodyPart> bodyParts = new LinkedList<>();
81+
bodyParts.add(new LazyResponseBodyPart(Unpooled.wrappedBuffer("Hello ".getBytes()), false));
82+
bodyParts.add(new LazyResponseBodyPart(Unpooled.wrappedBuffer("World".getBytes()), true));
83+
NettyResponse response = new NettyResponse(new NettyResponseStatus(null, null, null), null, bodyParts);
84+
85+
ByteBuf body = response.getResponseBodyAsByteBuf();
86+
assertEquals("Hello World", body.toString(StandardCharsets.UTF_8));
87+
body.release();
88+
}
7689
}

0 commit comments

Comments
 (0)