Juega 2.5: obtén un cuerpo de respuesta en acción http personalizada

Estoy intentando crear una acción http personalizada ( https://playframework.com/documentation/2.5.x/JavaActionsComposition ) para registrar cuerpos de solicitud y respuesta con Play 2.5.0 Java. Esto es lo que tengo hasta ahora:

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

El registro a menudo se considera una característica transversal. En tales casos, la forma preferida de hacer esto en Play es usar Filtros:

El filtro API está destinado a cuestiones transversales que se aplican indiscriminadamente a todas las rutas. Por ejemplo, aquí hay algunos casos de uso comunes para los filtros:

  • Logging / colección de métricas.
  • Codificacion GZIP
  • Encabezados de seguridad

Esto funciona para mí:

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

¿Qué está haciendo?

Primero, esto crea un nuevo filtro que se puede usar junto con otros filtros que pueda tener. Para obtener el cuerpo de la respuesta, en realidad usamos el siguiente nextFilter : una vez que tenemos la respuesta, podemos obtener el cuerpo.

A partir de Play 2.5 Akka Streams es el arma de elección. Esto significa que una vez que use el JavaResultExtractor , obtendrá una ByteString , que luego tendrá que decodificar para obtener la cadena real debajo.


Tenga en cuenta que no debería haber ningún problema al copiar esta lógica en la Action que está creando. Simplemente elegí la opción con Filter por el motivo que se indica en la parte superior de mi publicación.