I would like to add a decorator to my armeria client that checks each http response if a certain http header was returned:
builder.decorator((delegate, ctx, req) -> {
final HttpResponse response = delegate.execute(ctx, req);
final AggregatedHttpResponse r = response.aggregate().join();
for (Map.Entry<AsciiString, String> header : r.headers()) {
if ("warning".equalsIgnoreCase(header.getKey().toString())) {
throw new IllegalArgumentException("Detected usage of deprecated API for request "
+ req.toString() + ":\n" + header.getValue());
}
}
return response;
});
However, when starting my client it blocks on the join()
call and waits forever. Is there a standard pattern for this in Armeria ? Presumably i cannot just block on the response in an interceptor, but i could not find a way to access the response headers otherwise. Using subscribe
or toDuplicator
did not work any better though.
There are two ways to achieve the desired behavior.
The first option is to aggregate the response asynchronously and then convert it back to an
HttpResponse
. The key APIs areAggregatedHttpResponse.toHttpResponse()
andHttpResponse.from(CompletionStage)
:This approach is fairly simple and straightforward, but it doesn't work for a streaming response, because it waits until the complete response body is ready.
If your service returns a potentially large streaming response, you can use a
FilteredHttpResponse
to filter the response without aggregating anything:It's slightly more verbose than the first option, but it does not buffer the response in the memory, which is great for large streaming responses.
Ideally, in the future, we'd like to add more operators to
HttpResponse
orStreamMessage
. Please stay tuned to this issue page and add any suggestions for better API: https://github.com/line/armeria/issues/3097