【问题标题】:Accessing response headers using a decorator in Armeria在 Armeria 中使用装饰器访问响应标头
【发布时间】:2021-01-19 02:43:12
【问题描述】:

我想向我的 armeria 客户端添加一个装饰器,如果返回了某个 http 标头,它会检查每个 http 响应:

    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;
    });

但是,当启动我的客户端时,它会阻止 join() 调用并永远等待。在 Armeria 有标准模式吗?大概我不能仅仅阻止拦截器中的响应,但是我找不到访问响应标头的方法。不过,使用subscribetoDuplicator 并没有更好的效果。

【问题讨论】:

  • 与问题没有直接关系,但您可以使用ResponseHeaders.contains(),因为 Armeria 中的标题名称始终是小写的。
  • 确实,感谢@trustin,您的以下建议非常有效!
  • 我的荣幸。让我期待您的更多问题????

标签: armeria


【解决方案1】:

有两种方法可以实现所需的行为。

第一个选项是异步聚合响应,然后将其转换回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();
    }));
});

这种方法相当简单直接,但不适用于流式响应,因为它会等到完整的响应主体准备好。

如果您的服务返回可能很大的流式响应,您可以使用FilteredHttpResponse 过滤响应而不聚合任何内容:

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;
        }
    };
});

它比第一个选项稍微冗长,但它不会在内存中缓冲响应,这对于大型流式响应非常有用。

理想情况下,我们希望将来向HttpResponseStreamMessage 添加更多运算符。请继续关注此问题页面并添加任何关于更好 API 的建议:https://github.com/line/armeria/issues/3097

【讨论】:

    猜你喜欢
    • 2020-06-30
    • 1970-01-01
    • 2019-10-04
    • 2023-03-06
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-16
    相关资源
    最近更新 更多