Play 2.5: get response body in custom http action

萝らか妹 提交于 2019-12-04 15:34:30

Logging is often considered a cross-cutting feature. In such cases the preferred way to do this in Play is to use Filters:

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

This works for me:

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

What is it doing?

First this creates a new Filter which can be used along with other filters you may have. In order to get the body of the response we actually use the nextFilter - once we have the response we can then get the body.

As of Play 2.5 Akka Streams are the weapon of choice. This means that once you use the JavaResultExtractor, you will get a ByteString, which you then have to decode in order to get the real string underneath.


Please keep in mind that there should be no problem in copying this logic in the Action that you are creating. I just chose the option with Filter because of the reason stated at the top of my post.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!