玩2.5:在自定义http动作中获取响应体

我正在尝试使用Play 2.5.0 Java创建自定义http操作( https://playframework.com/documentation/2.5.x/JavaActionsComposition )来记录请求和响应主体。 这是我到目前为止所得到的:

public class Log extends play.mvc.Action.Simple { public CompletionStage call(Http.Context ctx) { CompletionStage response = delegate.call(ctx); //request body is fine System.out.println(ctx.request().body().asText()) //how to get response body string here while also not sabotaging http response flow of the framework? //my guess is it should be somehow possible to access it below? response.thenApply( r -> { //??? return null; }); return response; } } 

记录通常被认为是一种交叉function。 在这种情况下,在Play中执行此操作的首选方法是使用filter:

filterAPI旨在用于不加选择地应用于所有路径的交叉切割问题。 例如,以下是filter的一些常见用例:

  • 记录/指标收集
  • GZIP编码
  • 安全标头

这对我有用:

 import java.util.concurrent.CompletionStage; import java.util.function.Function; import javax.inject.Inject; import akka.stream.*; import play.Logger; import play.mvc.*; public class LoggingFilter extends Filter { Materializer mat; @Inject public LoggingFilter(Materializer mat) { super(mat); this.mat = mat; } @Override public CompletionStage apply( Function> nextFilter, Http.RequestHeader requestHeader) { long startTime = System.currentTimeMillis(); return nextFilter.apply(requestHeader).thenApply(result -> { long endTime = System.currentTimeMillis(); long requestTime = endTime - startTime; Logger.info("{} {} took {}ms and returned {}", requestHeader.method(), requestHeader.uri(), requestTime, result.status()); akka.util.ByteString body = play.core.j.JavaResultExtractor.getBody(result, 10000l, mat); Logger.info(body.decodeString("UTF-8")); return result.withHeader("Request-Time", "" + requestTime); }); } } 

它在做什么?

首先,这会创建一个新的filter,可以与您可能拥有的其他filter一起使用。 为了获得响应的主体,我们实际上使用了nextFilter – 一旦我们得到响应,我们就可以得到正文。

从Play 2.5开始, Akka Streams是首选武器。 这意味着一旦你使用JavaResultExtractor ,你将得到一个ByteString ,然后你必须解码才能得到真正的字符串。


请记住,在您正在创建的Action中复制此逻辑应该没有问题。 我刚刚选择了Filter选项,因为我在post顶部说明了原因。