玩2.5:在自定义http动作中获取响应体 [英] Play 2.5: get response body in custom http action

查看:137
本文介绍了玩2.5:在自定义http动作中获取响应体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to create a custom http action (https://playframework.com/documentation/2.5.x/JavaActionsComposition) to log request and response bodies with Play 2.5.0 Java. This is what I've got so far:

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中执行此操作的首选方法是使用过滤器:

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


过滤器API用于应用的交叉切割问题不分青红皂白地对所有路线。例如,以下是过滤器的一些常见用例:

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:


  • 日志记录/指标集合

  • GZIP编码

  • 安全标题






这对我有用:


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

它在做什么?

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

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.

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

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.

请记住,在<$中复制此逻辑应该没有问题您正在创建的c $ c>操作。我刚刚选择过滤器的选项,因为我在帖子顶部说明了原因。

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.

这篇关于玩2.5:在自定义http动作中获取响应体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆