玩 2.5:在自定义 http 操作中获取响应正文
Play 2.5: get response body in custom http action
我正在尝试创建自定义 http 操作 (https://playframework.com/documentation/2.5.x/JavaActionsComposition) 以使用 Play 2.5.0 Java 记录请求和响应主体。这是我到目前为止得到的:
public class Log extends play.mvc.Action.Simple {
public CompletionStage<Result> call(Http.Context ctx) {
CompletionStage<Result> 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;
}
}
日志记录通常被认为是一个跨领域的特性。在这种情况下,在 Play 中执行此操作的首选方法是使用过滤器:
The filter API is intended for cross cutting concerns that are applied indiscriminately to all routes. For example, here are some common use cases for filters:
- Logging/metrics collection
- GZIP encoding
- Security headers
这对我有用:
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<Result> apply(
Function<Http.RequestHeader, CompletionStage<Result>> 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);
});
}
}
它在做什么?
首先,这会创建一个新的过滤器,它可以与您可能拥有的其他过滤器一起使用。为了获得响应的主体,我们实际上使用 nextFilter
- 一旦我们有了响应,我们就可以得到主体。
从 Play 2.5 开始 Akka Streams 是首选武器。这意味着一旦你使用 JavaResultExtractor
,你将得到一个 ByteString
,然后你必须对其进行解码以获得下面的真实字符串。
请记住,在您正在创建的 Action
中复制此逻辑应该没有问题。由于 post.
顶部所述的原因,我刚刚选择了带有 Filter
的选项
我正在尝试创建自定义 http 操作 (https://playframework.com/documentation/2.5.x/JavaActionsComposition) 以使用 Play 2.5.0 Java 记录请求和响应主体。这是我到目前为止得到的:
public class Log extends play.mvc.Action.Simple {
public CompletionStage<Result> call(Http.Context ctx) {
CompletionStage<Result> 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;
}
}
日志记录通常被认为是一个跨领域的特性。在这种情况下,在 Play 中执行此操作的首选方法是使用过滤器:
The filter API is intended for cross cutting concerns that are applied indiscriminately to all routes. For example, here are some common use cases for filters:
- Logging/metrics collection
- GZIP encoding
- Security headers
这对我有用:
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<Result> apply(
Function<Http.RequestHeader, CompletionStage<Result>> 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);
});
}
}
它在做什么?
首先,这会创建一个新的过滤器,它可以与您可能拥有的其他过滤器一起使用。为了获得响应的主体,我们实际上使用 nextFilter
- 一旦我们有了响应,我们就可以得到主体。
从 Play 2.5 开始 Akka Streams 是首选武器。这意味着一旦你使用 JavaResultExtractor
,你将得到一个 ByteString
,然后你必须对其进行解码以获得下面的真实字符串。
请记住,在您正在创建的 Action
中复制此逻辑应该没有问题。由于 post.
Filter
的选项