java - 如何在 Java 11 中读取 HttpRequest 的正文?

标签 java httprequest java-11 java-http-client java-flow

在测试中,我想查看 HttpRequest 的主体内部。我想把 body 当作一根绳子。似乎唯一的方法就是订阅 BodyPublisher,但是这是如何工作的呢?

最佳答案

这是一个有趣的问题。您从哪里获取 HttpRequest ?最简单的方法是直接从创建 HttpRequest 的代码中获取正文。如果这是不可能的,那么下一步就是克隆该请求并将其正文发布者包装在您自己的 BodyPublisher 实现中,然后再通过 HttpClient 发送请求。编写 HttpRequest 的子类应该相对容易(如果乏味),它包装 HttpRequest 的另一个实例并将每个调用委托(delegate)给包装的实例,但覆盖 HttpRequest::bodyPublisher 执行以下操作:

return request.bodyPublisher().map(this::wrapBodyPublisher);

否则,您也可以尝试订阅请求正文发布者并从中获取正文字节 - 但请注意,并非 BodyPublisher 的所有实现都可以支持多个订阅者(无论是并发还是顺序) 。

为了说明我上面的建议:类似于下面的内容可能会起作用,具体取决于正文发布者的具体实现,并且前提是您可以防止对正文发布者的并发订阅。也就是说,在一个受控的测试环境中,您了解所有各方,那么它可能是可行的。不要在生产中使用任何这样的东西:

public class HttpRequestBody {

    // adapt Flow.Subscriber<List<ByteBuffer>> to Flow.Subscriber<ByteBuffer>
    static final class StringSubscriber implements Flow.Subscriber<ByteBuffer> {
        final BodySubscriber<String> wrapped;
        StringSubscriber(BodySubscriber<String> wrapped) {
            this.wrapped = wrapped;
        }
        @Override
        public void onSubscribe(Flow.Subscription subscription) {
            wrapped.onSubscribe(subscription);
        }
        @Override
        public void onNext(ByteBuffer item) { wrapped.onNext(List.of(item)); }
        @Override
        public void onError(Throwable throwable) { wrapped.onError(throwable); }
        @Override
        public void onComplete() { wrapped.onComplete(); }
    }

    public static void main(String[] args) throws Exception {
        var request = HttpRequest.newBuilder(new URI("http://example.com/blah"))
                .POST(BodyPublishers.ofString("Lorem ipsum dolor sit amet"))
                .build();

        // you must be very sure that nobody else is concurrently 
        // subscribed to the body publisher when executing this code,
        // otherwise one of the subscribers is likely to fail.
        String reqbody = request.bodyPublisher().map(p -> {
            var bodySubscriber = BodySubscribers.ofString(StandardCharsets.UTF_8);
            var flowSubscriber = new StringSubscriber(bodySubscriber);
            p.subscribe(flowSubscriber);
            return bodySubscriber.getBody().toCompletableFuture().join();
        }).get();
        System.out.println(reqbody);
    }

}

关于java - 如何在 Java 11 中读取 HttpRequest 的正文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55816226/

相关文章:

java - 从数据库生成模型类

java - 如何将我的 spring xml 配置移到我的 web 应用程序之外?

bash - 使用 HTTP 请求在 privnote.com 中创建注释

node.js - 谷歌云功能从第三方服务器获取数据

java - IntelliJ 无法使用 OpenJDK 11 识别 JavaFX 11

itext - iText PDF FontFactory.registerDirectories() 和 Java 11 的非法反射访问操作警告

java - 是否可以将 "tail -f"命令的输出获取到 java 程序?

java - 字符串的正则表达式包含

rest - PATCH 方法是否应该在响应正文中返回资源的所有字段?

Java11 嵌套类,同时对代码使用 Fluent Design Structure