gpt4 book ai didi

playframework - 在 PlayFramework 中修改 http 结果的正文

转载 作者:行者123 更新时间:2023-12-04 03:44:58 28 4
gpt4 key购买 nike

我正在使用 PlayFramework 的 2.0.2 版本,并且正在尝试创建一个游戏play.mvc.Action实现 后置过滤器 对于 http 结果。

play docs 中解释了使用 actor 进行预处理的示例。 .

但是我想要实现的有点不同。我需要:

  • 拍下play.mvc.Result
  • 提取正文
  • 对 body 应用变换
  • 然后创建一个新的结果。
  • Result接口(interface) 不暴露 http 正文 ,甚至假设您有特定的子类(例如 SimpleResultAsyncResult )我不确定如何提取消息正文。

    我的具体用例是对结果正文进行 GZip 过滤并添加正确的“内容编码” header 。我希望能够应用此 GZip通过添加注释来过滤到任何现有的 Controller ,类似于在文档中实现身份验证的方式。

    下面是我正在尝试做的一个例子
    public class Compress {
    @With(GZipResult.class)
    public @interface GZip {
    }

    public static class GZipResult extends Action<GZip> {
    @Override
    public Result call(Http.Context ctx) throws Throwable {
    Result result = delegate.call(ctx);
    if (requestSupportsGZip(ctx) {
    result = extractAndGZipResult(result); //how to extract http body?
    }
    return result;
    }
    }
    }

    可以用作
    @Compress.GZip
    class MyController extends Controller {
    public static Result index() {
    return ok(someHtml);
    }
    }

    最佳答案

    我在修改 http 结果时遇到了类似的情况。我想分享我在 Java 中处理这个问题的方法。

    在检查 Play 2.0.3 的 Scala 源代码后,我发现 play.core.j.JavaResultExtractor可以检索 Result 的响应正文、cookie、 header 和状态Java 中的类和 play.core.j.JavaResults可以写响应体的内容。

    尽管如此,我仍然不知道如何以简单的方式用修改后的主体替换当前的响应主体。也许用 Scala 实现处理这个问题会更容易,但我仍然发现 Scala 太难读了:-(

    我找到的方法是看play.mvc.Results.Status已实现,它使用 play.core.j.JavaResults编写内容正文。我提到的类是 ok() 的核心, notFound() , forbidden() ,以及生成Result 的其他类似方法在 Controller Java 中的类。此类的实现如下所示:(重构 Scala 类以提高可读性)

    // scala classes
    import play.api.mvc.Codec;
    import play.api.mvc.Content;
    import play.core.j.JavaResults;
    // ...

    public static class Status implements Result {
    final private play.api.mvc.Result wrappedResult;
    // ...

    // there are a lot of constructors for this class to reference from
    // this particular constructor is the general approach for most cases
    public Status(play.api.mvc.Results.Status status, Content content, Codec codec) {
    // ...
    wrappedResult = status.apply(
    content,
    JavaResults.writeContent(codec),
    JavaResults.contentTypeOf(content.contentType() + "; charset=" + codec.charset())
    );
    }

    }

    如果你想实现上面的代码,你还需要实现 play.api.mvc.Content界面。总而言之,按照我所说的实现你的代码看起来像这样:

    import play.api.mvc.Codec;
    import play.api.mvc.Content;
    import play.core.j.JavaResultExtractor;
    import play.core.j.JavaResults;
    // ...

    public static class GZipResult extends Action<GZip> {

    @Override
    public Result call(Http.Context ctx) throws Throwable {
    Result result = delegate.call(ctx);
    if (requestSupportsGZip(ctx)) {
    // copy parts of current response
    final int statusCode = JavaResultExtractor.getStatus(result);
    final Map<String,String> headers = JavaResultExtractor.getHeaders(result);
    final byte[] body = JavaResultExtractor.getBody(result);

    // create a gzip result
    result = new GZipResult(statusCode, new String(body), headers.get("Content-Type"));

    // add appropriate headers here
    // ...
    }

    return result;
    }
    }

    private static class GZipResult implements Result {
    final private play.api.mvc.Result wrappedResult;

    public GZipResult(final int StatusCode, final String content, final String contentType) {
    if(content == null) throw new NullPointerException("null content");

    // i guess this is the good place in transforming the content body
    String gzippedContent = someMethodToGzipContent(content);

    this.wrappedResult = JavaResults.Status(statusCode).apply(
    // implement the play.api.mvc.Content interface
    new Content() {
    @Override public String body() { return gzippedContent; }
    @Override public String contentType() { return contentType; }
    },
    JavaResults.writeContent(Codec.utf_8),
    JavaResults.contentTypeOf(contentType))
    );
    }

    // ...
    }

    通过上面的实现,我可以修改 http 结果。我希望这可以为您的特定用例提供帮助。

    干杯!

    更新

    上面的代码可以解决大多数修改 http 结果的用例。您的特殊情况,即 gzipping 响应,需要另一种方法,因为 gzipped 正文位于 byte[] 中。不在 String . play.mvc.Results.Status类还提供处理 byte[] 的方法.实现如下所示:

    // scala classes
    import play.core.j.JavaResults;
    // ...

    public static class Status implements Result {
    final private play.api.mvc.Result wrappedResult;
    // ...

    public Status(play.api.mvc.Results.Status status, byte[] content) {
    // ...
    wrappedResult = status.apply(
    content,
    JavaResults.writeBytes(),
    JavaResults.contentTypeOfBytes()
    );
    }

    }

    您可以在我更新之前根据我的实现找出如何对您的代码执行此操作。请注意,您不需要实现 play.api.mvc.Content并确保在响应中返回适当的内容类型。

    快乐编码:-)

    关于playframework - 在 PlayFramework 中修改 http 结果的正文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12189146/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com