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

时间:2019-04-23 17:07:53

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

在测试中,我想查看HttpRequest的正文。我想把琴弦当作琴弦。似乎唯一的方法是订阅BodyPublisher,但这是如何工作的?

2 个答案:

答案 0 :(得分:2)

您为什么不只使用"official" OpenJDK HttpRequest recipe

第一个食谱完全可以满足您的需求:

public void get(String uri) throws Exception {
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
          .uri(URI.create(uri))
          .build();

    HttpResponse<String> response =
          client.send(request, BodyHandlers.ofString());

    System.out.println(response.body());
}

答案 1 :(得分:0)

这是一个有趣的问题。您从哪里得到HttpRequest?最简单的方法是直接从创建HttpRequest的代码中获取主体。如果那不可能,那么下一步是克隆该请求,并将其主体发布者包装在您自己的BodyPublisher实现中,然后再通过HttpClient发送请求。编写HttpRequest的子类来包装HttpRequest的另一个实例,并将每个调用委派给包装的实例,但重写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);
    }

}