armeria - Accessing response headers using a decorator in Armeria
问题描述
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.
解决方案
有两种方法可以实现所需的行为。
第一个选项是异步聚合响应,然后将其转换回HttpResponse
. 关键 API 是AggregatedHttpResponse.toHttpResponse()
和HttpResponse.from(CompletionStage)
:
builder.decorator(delegate, ctx, req) -> {
final HttpResponse res = delegate.serve(ctx, req);
return HttpResponse.from(res.aggregate().thenApply(r -> {
final ResponseHeaders headers = r.headers();
if (headers...) {
throw new IllegalArgumentException();
}
// Convert AggregatedHttpResponse back to HttpResponse.
return r.toHttpResponse();
}));
});
这种方法相当简单直接,但它不适用于流式响应,因为它会等到完整的响应主体准备好。
如果您的服务返回可能很大的流式响应,您可以使用 aFilteredHttpResponse
过滤响应而不聚合任何内容:
builder.decorator(delegate, ctx, req) -> {
final HttpResponse res = delegate.serve(ctx, req);
return new FilteredHttpResponse(res) {
@Override
public HttpObject filter(HttpObject obj) {
// Ignore other objects like HttpData.
if (!(obj instanceof ResponseHeaders)) {
return obj;
}
final ResponseHeaders headers = (ResponseHeaders) obj;
if (headers...) {
throw new IllegalArgumentException();
}
return obj;
}
};
});
它比第一个选项稍微冗长,但它不会在内存中缓冲响应,这对于大型流式响应非常有用。
理想情况下,将来我们希望在HttpResponse
or中添加更多运算符StreamMessage
。请继续关注此问题页面并添加任何关于更好 API 的建议:https ://github.com/line/armeria/issues/3097
推荐阅读
- javascript - 如何找到具有指向当前 DIV 或 textarea 的“for”属性的标签
- sql - 在 SQL 中使用“AND”操作获得空结果,使用“OR”操作获得错误结果
- javascript - ReferenceError:文档未定义(atom ide)
- ionic-framework - 离子启动项目时远程代码执行错误
- python - Python - Jupyter 笔记本的总运行时间
- android - 使用数据绑定无法正常工作的 XML 文件中的格式化字符串绑定
- javascript - 动态添加目标属性,该属性作为 HTML 代码块存在于 JS 变量中
- c# - 如何查找日期范围之间的匹配时间
- reactjs - 检查 `Formik` 的渲染方法
- node.js - 出现此错误时,PM2 不会重新启动 Node JS 应用程序