Skip to content

Commit faec37f

Browse files
committed
#23 - ENH: Add CompletableFuture asByteArray(), asLines() asInputStream()
1 parent 91bd867 commit faec37f

File tree

3 files changed

+109
-9
lines changed

3 files changed

+109
-9
lines changed

client/src/main/java/io/avaje/http/client/DHttpAsync.java

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.avaje.http.client;
22

3+
import java.io.InputStream;
34
import java.net.http.HttpResponse;
45
import java.util.List;
56
import java.util.concurrent.CompletableFuture;
@@ -13,30 +14,48 @@ class DHttpAsync implements HttpAsyncResponse {
1314
this.request = request;
1415
}
1516

16-
@Override
17-
public <E> CompletableFuture<HttpResponse<E>> withHandler(HttpResponse.BodyHandler<E> handler) {
17+
private <E> CompletableFuture<HttpResponse<E>> with(boolean loggable, HttpResponse.BodyHandler<E> handler) {
1818
return request
19-
.performSendAsync(false, handler)
19+
.performSendAsync(loggable, handler)
2020
.thenApply(request::afterAsync);
2121
}
2222

23+
@Override
24+
public <E> CompletableFuture<HttpResponse<E>> withHandler(HttpResponse.BodyHandler<E> handler) {
25+
return with(false, handler);
26+
}
27+
2328
@Override
2429
public CompletableFuture<HttpResponse<Void>> asDiscarding() {
25-
return withHandler(HttpResponse.BodyHandlers.discarding());
30+
return with(false, HttpResponse.BodyHandlers.discarding());
2631
}
2732

2833
@Override
2934
public CompletableFuture<HttpResponse<Void>> asVoid() {
35+
// read the response content as bytes so that it is available for error response
3036
return request
3137
.performSendAsync(true, HttpResponse.BodyHandlers.ofByteArray())
3238
.thenApply(request::asyncVoid);
3339
}
3440

3541
@Override
3642
public CompletableFuture<HttpResponse<String>> asString() {
37-
return request
38-
.performSendAsync(true, HttpResponse.BodyHandlers.ofString())
39-
.thenApply(request::afterAsync);
43+
return with(true, HttpResponse.BodyHandlers.ofString());
44+
}
45+
46+
@Override
47+
public CompletableFuture<HttpResponse<byte[]>> asByteArray() {
48+
return with(true, HttpResponse.BodyHandlers.ofByteArray());
49+
}
50+
51+
@Override
52+
public CompletableFuture<HttpResponse<Stream<String>>> asLines() {
53+
return with(false, HttpResponse.BodyHandlers.ofLines());
54+
}
55+
56+
@Override
57+
public CompletableFuture<HttpResponse<InputStream>> asInputStream() {
58+
return with(false, HttpResponse.BodyHandlers.ofInputStream());
4059
}
4160

4261
@Override

client/src/main/java/io/avaje/http/client/HttpAsyncResponse.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.avaje.http.client;
22

3+
import java.io.InputStream;
34
import java.net.http.HttpResponse;
45
import java.util.List;
56
import java.util.concurrent.CompletableFuture;
@@ -110,6 +111,27 @@ public interface HttpAsyncResponse {
110111
*/
111112
CompletableFuture<HttpResponse<String>> asString();
112113

114+
/**
115+
* Process as response {@literal HttpResponse<byte[]>}.
116+
*
117+
* @return The CompletableFuture of the response
118+
*/
119+
CompletableFuture<HttpResponse<byte[]>> asByteArray();
120+
121+
/**
122+
* Process as response {@literal HttpResponse<Stream<String>>}.
123+
*
124+
* @return The CompletableFuture of the response
125+
*/
126+
CompletableFuture<HttpResponse<Stream<String>>> asLines();
127+
128+
/**
129+
* Process as response {@literal HttpResponse<InputStream>}.
130+
*
131+
* @return The CompletableFuture of the response
132+
*/
133+
CompletableFuture<HttpResponse<InputStream>> asInputStream();
134+
113135
/**
114136
* Process with any given {@code HttpResponse.BodyHandler}.
115137
*
@@ -147,10 +169,10 @@ public interface HttpAsyncResponse {
147169
* });
148170
* }</pre>
149171
*
150-
* @param bodyHandlers The body handler to use to process the response
172+
* @param bodyHandler The body handler to use to process the response
151173
* @return The CompletableFuture of the response
152174
*/
153-
<E> CompletableFuture<HttpResponse<E>> withHandler(HttpResponse.BodyHandler<E> bodyHandlers);
175+
<E> CompletableFuture<HttpResponse<E>> withHandler(HttpResponse.BodyHandler<E> bodyHandler);
154176

155177
/**
156178
* Process expecting a bean response body (typically from json content).

client/src/test/java/io/avaje/http/client/HelloControllerTest.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.io.*;
88
import java.net.http.HttpClient;
99
import java.net.http.HttpResponse;
10+
import java.nio.charset.StandardCharsets;
1011
import java.nio.file.Path;
1112
import java.time.Duration;
1213
import java.time.LocalDate;
@@ -58,6 +59,22 @@ void asLines() {
5859
assertThat(lines.get(0)).contains("{\"id\":1, \"name\":\"one\"}");
5960
}
6061

62+
@Test
63+
void asLines_async() throws ExecutionException, InterruptedException {
64+
final CompletableFuture<HttpResponse<Stream<String>>> future = clientContext.request()
65+
.path("hello").path("stream")
66+
.GET()
67+
.async()
68+
.asLines();
69+
70+
final HttpResponse<Stream<String>> hres = future.get();
71+
assertThat(hres.statusCode()).isEqualTo(200);
72+
final List<String> lines = hres.body().collect(Collectors.toList());
73+
74+
assertThat(lines).hasSize(4);
75+
assertThat(lines.get(0)).contains("{\"id\":1, \"name\":\"one\"}");
76+
}
77+
6178
@Test
6279
void asInputStream() throws IOException {
6380
final HttpResponse<InputStream> hres =
@@ -78,6 +95,26 @@ void asInputStream() throws IOException {
7895
assertThat(allLines.get(0)).contains("{\"id\":1, \"name\":\"one\"}");
7996
}
8097

98+
@Test
99+
void asInputStream_async() throws IOException, ExecutionException, InterruptedException {
100+
final CompletableFuture<HttpResponse<InputStream>> future = clientContext.request()
101+
.path("hello").path("stream")
102+
.GET()
103+
.async().asInputStream();
104+
105+
final HttpResponse<InputStream> hres = future.get();
106+
assertThat(hres.statusCode()).isEqualTo(200);
107+
final LineNumberReader reader = new LineNumberReader(new InputStreamReader(hres.body()));
108+
109+
List<String> allLines = new ArrayList<>();
110+
String line;
111+
while ((line = reader.readLine()) != null) {
112+
allLines.add(line);
113+
}
114+
assertThat(allLines).hasSize(4);
115+
assertThat(allLines.get(0)).contains("{\"id\":1, \"name\":\"one\"}");
116+
}
117+
81118
@Test
82119
void asFile() throws IOException {
83120
final Path path = File.createTempFile("test", "dump").toPath();
@@ -241,6 +278,28 @@ void get_helloMessage() {
241278
assertThat(hres.statusCode()).isEqualTo(200);
242279
}
243280

281+
@Test
282+
void asByteArray() {
283+
final HttpResponse<byte[]> hres = clientContext.request()
284+
.path("hello").path("message")
285+
.GET().asByteArray();
286+
287+
final byte[] body = hres.body();
288+
assertThat(new String(body, StandardCharsets.UTF_8)).contains("hello world");
289+
assertThat(hres.statusCode()).isEqualTo(200);
290+
}
291+
292+
@Test
293+
void asByteArray_async() throws ExecutionException, InterruptedException {
294+
final CompletableFuture<HttpResponse<byte[]>> future = clientContext.request()
295+
.path("hello").path("message")
296+
.GET().async().asByteArray();
297+
298+
final HttpResponse<byte[]> hres = future.get();
299+
assertThat(new String(hres.body(), StandardCharsets.UTF_8)).contains("hello world");
300+
assertThat(hres.statusCode()).isEqualTo(200);
301+
}
302+
244303
@Test
245304
void get_notFound() {
246305
UUID nullUUID = null;

0 commit comments

Comments
 (0)