Skip to content

Commit 2219220

Browse files
authored
Merge pull request #132 from avaje/feature/client-asResponsesWithHttpStatusAndHeaders
[http-client] ENH: Add response as() methods that return HttpResponse wrapping bean, list and stream
2 parents b60f87b + 7151aa1 commit 2219220

File tree

8 files changed

+497
-92
lines changed

8 files changed

+497
-92
lines changed

http-client/src/main/java/io/avaje/http/client/BodyAdapter.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ default <T> BodyReader<T> beanReader(ParameterizedType type) {
3333
throw new UnsupportedOperationException("Parameterized types not supported for this adapter");
3434
}
3535

36-
3736
/**
3837
* Return a BodyReader to read response content and convert to a list of beans.
3938
*

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

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -61,43 +61,72 @@ public CompletableFuture<HttpResponse<InputStream>> asInputStream() {
6161

6262
@Override
6363
public <E> CompletableFuture<E> bean(Class<E> type) {
64-
return request
65-
.performSendAsync(true, HttpResponse.BodyHandlers.ofByteArray())
66-
.thenApply(httpResponse -> request.asyncBean(type, httpResponse));
64+
return as(type).thenApply(HttpResponse::body);
6765
}
6866

6967
@Override
70-
public <E> CompletableFuture<List<E>> list(Class<E> type) {
71-
return request
72-
.performSendAsync(true, HttpResponse.BodyHandlers.ofByteArray())
73-
.thenApply(httpResponse -> request.asyncList(type, httpResponse));
68+
public <E> CompletableFuture<E> bean(ParameterizedType type) {
69+
final CompletableFuture<HttpResponse<E>> future = as(type);
70+
return future.thenApply(HttpResponse::body);
7471
}
7572

7673
@Override
77-
public <E> CompletableFuture<Stream<E>> stream(Class<E> type) {
78-
return request
79-
.performSendAsync(false, HttpResponse.BodyHandlers.ofLines())
80-
.thenApply(httpResponse -> request.asyncStream(type, httpResponse));
74+
public <E> CompletableFuture<HttpResponse<E>> as(Class<E> type) {
75+
return asyncAsBytes().thenApply(httpResponse -> request.asyncBean(type, httpResponse));
8176
}
8277

8378
@Override
84-
public <E> CompletableFuture<E> bean(ParameterizedType type) {
85-
return request
86-
.performSendAsync(true, HttpResponse.BodyHandlers.ofByteArray())
87-
.thenApply(httpResponse -> request.asyncBean(type, httpResponse));
79+
public <E> CompletableFuture<HttpResponse<E>> as(ParameterizedType type) {
80+
return asyncAsBytes().thenApply(httpResponse -> request.asyncBean(type, httpResponse));
81+
}
82+
83+
@Override
84+
public <E> CompletableFuture<List<E>> list(Class<E> type) {
85+
return asList(type).thenApply(HttpResponse::body);
8886
}
8987

9088
@Override
9189
public <E> CompletableFuture<List<E>> list(ParameterizedType type) {
92-
return request
93-
.performSendAsync(true, HttpResponse.BodyHandlers.ofByteArray())
94-
.thenApply(httpResponse -> request.asyncList(type, httpResponse));
90+
final CompletableFuture<HttpResponse<List<E>>> future = asList(type);
91+
return future.thenApply(HttpResponse::body);
92+
}
93+
94+
@Override
95+
public <E> CompletableFuture<HttpResponse<List<E>>> asList(Class<E> type) {
96+
return asyncAsBytes().thenApply(httpResponse -> request.asyncList(type, httpResponse));
97+
}
98+
99+
@Override
100+
public <E> CompletableFuture<HttpResponse<List<E>>> asList(ParameterizedType type) {
101+
return asyncAsBytes().thenApply(httpResponse -> request.asyncList(type, httpResponse));
102+
}
103+
104+
@Override
105+
public <E> CompletableFuture<Stream<E>> stream(Class<E> type) {
106+
return asStream(type).thenApply(HttpResponse::body);
95107
}
96108

97109
@Override
98110
public <E> CompletableFuture<Stream<E>> stream(ParameterizedType type) {
99-
return request
100-
.performSendAsync(false, HttpResponse.BodyHandlers.ofLines())
101-
.thenApply(httpResponse -> request.asyncStream(type, httpResponse));
111+
final CompletableFuture<HttpResponse<Stream<E>>> future = asStream(type);
112+
return future.thenApply(HttpResponse::body);
113+
}
114+
115+
@Override
116+
public <E> CompletableFuture<HttpResponse<Stream<E>>> asStream(Class<E> type) {
117+
return asyncAsLines().thenApply(httpResponse -> request.asyncStream(type, httpResponse));
118+
}
119+
120+
@Override
121+
public <E> CompletableFuture<HttpResponse<Stream<E>>> asStream(ParameterizedType type) {
122+
return asyncAsLines().thenApply(httpResponse -> request.asyncStream(type, httpResponse));
123+
}
124+
125+
private CompletableFuture<HttpResponse<byte[]>> asyncAsBytes() {
126+
return request.performSendAsync(true, HttpResponse.BodyHandlers.ofByteArray());
127+
}
128+
129+
private CompletableFuture<HttpResponse<Stream<String>>> asyncAsLines() {
130+
return request.performSendAsync(false, HttpResponse.BodyHandlers.ofLines());
102131
}
103132
}

http-client/src/main/java/io/avaje/http/client/DHttpClientContext.java

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -269,29 +269,30 @@ <T> BodyContent write(T bean, String contentType) {
269269
return bodyAdapter.beanWriter(bean.getClass()).write(bean, contentType);
270270
}
271271

272-
<T> BodyReader<T> beanReader(Class<T> cls) {
273-
return bodyAdapter.beanReader(cls);
272+
<T> BodyReader<T> beanReader(Class<T> type) {
273+
return bodyAdapter.beanReader(type);
274274
}
275275

276-
<T> BodyReader<T> beanReader(ParameterizedType cls) {
277-
return bodyAdapter.beanReader(cls);
276+
<T> BodyReader<T> beanReader(ParameterizedType type) {
277+
return bodyAdapter.beanReader(type);
278278
}
279279

280-
<T> T readBean(Class<T> cls, BodyContent content) {
281-
return bodyAdapter.beanReader(cls).read(content);
280+
<T> T readBean(Class<T> type, BodyContent content) {
281+
return bodyAdapter.beanReader(type).read(content);
282282
}
283283

284-
<T> List<T> readList(Class<T> cls, BodyContent content) {
285-
return bodyAdapter.listReader(cls).read(content);
284+
<T> List<T> readList(Class<T> type, BodyContent content) {
285+
return bodyAdapter.listReader(type).read(content);
286286
}
287287

288288
@SuppressWarnings("unchecked")
289-
<T> T readBean(ParameterizedType cls, BodyContent content) {
290-
return (T) bodyAdapter.beanReader(cls).read(content);
289+
<T> T readBean(ParameterizedType type, BodyContent content) {
290+
return (T) bodyAdapter.beanReader(type).read(content);
291291
}
292292

293-
<T> List<T> readList(ParameterizedType cls, BodyContent content) {
294-
return (List<T>) bodyAdapter.listReader(cls).read(content);
293+
@SuppressWarnings("unchecked")
294+
<T> List<T> readList(ParameterizedType type, BodyContent content) {
295+
return (List<T>) bodyAdapter.listReader(type).read(content);
295296
}
296297

297298
void afterResponse(DHttpClientRequest request) {

http-client/src/main/java/io/avaje/http/client/DHttpClientRequest.java

Lines changed: 78 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ private void readResponseContent() {
414414
@Override
415415
public HttpResponse<Void> asVoid() {
416416
readResponseContent();
417-
return new HttpVoidResponse(httpResponse);
417+
return new HttpWrapperResponse<>(httpResponse);
418418
}
419419

420420
@Override
@@ -424,50 +424,75 @@ public <T> T read(BodyReader<T> reader) {
424424
}
425425

426426
@Override
427-
public <T> T bean(Class<T> cls) {
427+
public <T> HttpResponse<T> as(Class<T> type) {
428+
return new HttpWrapperResponse<>(bean(type), httpResponse);
429+
}
430+
431+
@Override
432+
public <T> HttpResponse<T> as(ParameterizedType type) {
433+
return new HttpWrapperResponse<>(bean(type), httpResponse);
434+
}
435+
436+
@Override
437+
public <T> T bean(Class<T> type) {
428438
readResponseContent();
429-
return context.readBean(cls, encodedResponseBody);
439+
return context.readBean(type, encodedResponseBody);
430440
}
431441

432442
@Override
433-
public <T> List<T> list(Class<T> cls) {
443+
public <T> T bean(ParameterizedType type) {
434444
readResponseContent();
435-
return context.readList(cls, encodedResponseBody);
445+
return context.readBean(type, encodedResponseBody);
436446
}
437447

438448
@Override
439-
public <T> Stream<T> stream(Class<T> cls) {
440-
final HttpResponse<Stream<String>> res = handler(HttpResponse.BodyHandlers.ofLines());
441-
this.httpResponse = res;
442-
if (res.statusCode() >= 300) {
443-
throw new HttpException(res, context);
444-
}
445-
final BodyReader<T> bodyReader = context.beanReader(cls);
446-
return res.body().map(bodyReader::readBody);
449+
public <T> HttpResponse<List<T>> asList(Class<T> type) {
450+
return new HttpWrapperResponse<>(list(type), httpResponse);
447451
}
448452

453+
@Override
454+
public <T> HttpResponse<List<T>> asList(ParameterizedType type) {
455+
return new HttpWrapperResponse<>(list(type), httpResponse);
456+
}
449457

450458
@Override
451-
public <T> T bean(ParameterizedType cls) {
459+
public <T> List<T> list(Class<T> type) {
452460
readResponseContent();
453-
return context.readBean(cls, encodedResponseBody);
461+
return context.readList(type, encodedResponseBody);
454462
}
455463

456464
@Override
457-
public <T> List<T> list(ParameterizedType cls) {
465+
public <T> List<T> list(ParameterizedType type) {
458466
readResponseContent();
459-
return context.readList(cls, encodedResponseBody);
467+
return context.readList(type, encodedResponseBody);
468+
}
469+
470+
@Override
471+
public <T> HttpResponse<Stream<T>> asStream(Class<T> type) {
472+
return new HttpWrapperResponse<>(stream(type), httpResponse);
473+
}
474+
475+
@Override
476+
public <T> HttpResponse<Stream<T>> asStream(ParameterizedType type) {
477+
return new HttpWrapperResponse<>(stream(type), httpResponse);
460478
}
461479

480+
@Override
481+
public <T> Stream<T> stream(Class<T> type) {
482+
return stream(context.beanReader(type));
483+
}
462484

463485
@Override
464-
public <T> Stream<T> stream(ParameterizedType cls) {
486+
public <T> Stream<T> stream(ParameterizedType type) {
487+
return stream(context.beanReader(type));
488+
}
489+
490+
private <T> Stream<T> stream(BodyReader<T> bodyReader) {
465491
final HttpResponse<Stream<String>> res = handler(HttpResponse.BodyHandlers.ofLines());
466492
this.httpResponse = res;
467493
if (res.statusCode() >= 300) {
468494
throw new HttpException(res, context);
469495
}
470-
final BodyReader<T> bodyReader = context.beanReader(cls);
471496
return res.body().map(bodyReader::readBody);
472497
}
473498

@@ -484,7 +509,7 @@ public <T> HttpResponse<T> handler(HttpResponse.BodyHandler<T> responseHandler)
484509
private <T> HttpResponse<T> sendWith(HttpResponse.BodyHandler<T> responseHandler) {
485510
context.beforeRequest(this);
486511
addHeaders();
487-
HttpResponse<T> response = performSend(responseHandler);
512+
final HttpResponse<T> response = performSend(responseHandler);
488513
httpResponse = response;
489514
return response;
490515
}
@@ -508,49 +533,49 @@ protected <T> CompletableFuture<HttpResponse<T>> performSendAsync(boolean loggab
508533

509534
protected HttpResponse<Void> asyncVoid(HttpResponse<byte[]> response) {
510535
afterAsyncEncoded(response);
511-
return new HttpVoidResponse(response);
536+
return new HttpWrapperResponse<>(response);
512537
}
513538

514-
protected <E> E asyncBean(Class<E> type, HttpResponse<byte[]> response) {
539+
protected <E> HttpResponse<E> asyncBean(Class<E> type, HttpResponse<byte[]> response) {
540+
afterAsyncEncoded(response);
541+
return new HttpWrapperResponse<>(context.readBean(type, encodedResponseBody), httpResponse);
542+
}
543+
544+
protected <E> E asyncBean(ParameterizedType type, HttpResponse<byte[]> response) {
515545
afterAsyncEncoded(response);
516546
return context.readBean(type, encodedResponseBody);
517547
}
518548

519-
protected <E> List<E> asyncList(Class<E> type, HttpResponse<byte[]> response) {
549+
protected <E> HttpResponse<List<E>> asyncList(Class<E> type, HttpResponse<byte[]> response) {
520550
afterAsyncEncoded(response);
521-
return context.readList(type, encodedResponseBody);
551+
return new HttpWrapperResponse<>(context.readList(type, encodedResponseBody), httpResponse);
552+
}
553+
554+
protected <E> HttpResponse<List<E>> asyncList(ParameterizedType type, HttpResponse<byte[]> response) {
555+
afterAsyncEncoded(response);
556+
return new HttpWrapperResponse<>(context.readList(type, encodedResponseBody), httpResponse);
522557
}
523558

524-
protected <E> Stream<E> asyncStream(Class<E> type, HttpResponse<Stream<String>> response) {
559+
protected <E> HttpResponse<Stream<E>> asyncStream(Class<E> type, HttpResponse<Stream<String>> response) {
525560
responseTimeNanos = System.nanoTime() - startAsyncNanos;
526561
httpResponse = response;
527562
context.afterResponse(this);
528563
if (response.statusCode() >= 300) {
529564
throw new HttpException(response, context);
530565
}
531566
final BodyReader<E> bodyReader = context.beanReader(type);
532-
return response.body().map(bodyReader::readBody);
567+
return new HttpWrapperResponse<>(response.body().map(bodyReader::readBody), httpResponse);
533568
}
534569

535-
protected <E> E asyncBean(ParameterizedType type, HttpResponse<byte[]> response) {
536-
afterAsyncEncoded(response);
537-
return context.readBean(type, encodedResponseBody);
538-
}
539-
540-
protected <E> List<E> asyncList(ParameterizedType type, HttpResponse<byte[]> response) {
541-
afterAsyncEncoded(response);
542-
return context.readList(type, encodedResponseBody);
543-
}
544-
545-
protected <E> Stream<E> asyncStream(ParameterizedType type, HttpResponse<Stream<String>> response) {
570+
protected <E> HttpResponse<Stream<E>> asyncStream(ParameterizedType type, HttpResponse<Stream<String>> response) {
546571
responseTimeNanos = System.nanoTime() - startAsyncNanos;
547572
httpResponse = response;
548573
context.afterResponse(this);
549574
if (response.statusCode() >= 300) {
550575
throw new HttpException(response, context);
551576
}
552577
final BodyReader<E> bodyReader = context.beanReader(type);
553-
return response.body().map(bodyReader::readBody);
578+
return new HttpWrapperResponse<>(response.body().map(bodyReader::readBody), httpResponse);
554579
}
555580

556581
private void afterAsyncEncoded(HttpResponse<byte[]> response) {
@@ -728,13 +753,20 @@ public String responseBody() {
728753
}
729754
}
730755

731-
static class HttpVoidResponse implements HttpResponse<Void> {
756+
static final class HttpWrapperResponse<B> implements HttpResponse<B> {
732757

733758
private final HttpResponse<?> orig;
759+
private final B body;
760+
761+
HttpWrapperResponse(HttpResponse<?> orig) {
762+
this.orig = orig;
763+
this.body = null;
764+
}
734765

735766
@SuppressWarnings({"raw"})
736-
HttpVoidResponse(HttpResponse<?> orig) {
767+
HttpWrapperResponse(B body, HttpResponse<?> orig) {
737768
this.orig = orig;
769+
this.body = body;
738770
}
739771

740772
@Override
@@ -747,9 +779,11 @@ public HttpRequest request() {
747779
return orig.request();
748780
}
749781

782+
@SuppressWarnings("unchecked")
750783
@Override
751-
public Optional<HttpResponse<Void>> previousResponse() {
752-
return Optional.empty();
784+
public Optional<HttpResponse<B>> previousResponse() {
785+
final Optional<? extends HttpResponse<?>> previous = orig.previousResponse();
786+
return (Optional<HttpResponse<B>>)previous;
753787
}
754788

755789
@Override
@@ -758,8 +792,8 @@ public HttpHeaders headers() {
758792
}
759793

760794
@Override
761-
public Void body() {
762-
return null;
795+
public B body() {
796+
return body;
763797
}
764798

765799
@Override

0 commit comments

Comments
 (0)