Как я могу получить код состояния для ответа, на который я подписываюсь, используя HttpClient JDK? - PullRequest
2 голосов
/ 07 мая 2019

Java 11 представила новый стандарт HTTP-клиент .Запрос отправляется с использованием HttpClient:send, который возвращает HttpResponse.

. Для поиска можно использовать метод HttpResponse::statusCode.HTTP-статус ответа.

HttpClient::send также принимает BodyHandler, который используется для обработки тела ответа.Полезное семейство BodyHandler с - это семейство, Flow.Subscription, созданное с BodyHandlers::fromSubscriber и родственниками.Это полезный способ работы с бесконечными потоками данных, такими как отправленные сервером события .

Однако, кажется, что если вы используете один из этих BodyHandler s, потокдоставляется в поток, который вызвал HttpClient::send, и поэтому для бесконечного потока этот метод никогда не возвращается.Поскольку он никогда не возвращается, вы никогда не получите HttpResponse, с помощью которого вы сможете определить статус.

Итак, как мне получить код состояния для ответа, на который я подписан?

1 Ответ

2 голосов
/ 07 мая 2019

Как отмечено в документации , эти BodyHandler с

не проверять код состояния, т. Е. Тело всегда принимается

с подсказкой, что

пользовательский обработчик может использоваться для проверки кода состояния и заголовков и возврата подходящего абонента тела того же типа, в зависимости от ситуации

Кажется, для этого нет удобного метода или класса, но такая вещь в меру проста:

// a subscriber which expresses a complete lack of interest in the body
private static class Unsubscriber implements HttpResponse.BodySubscriber<Void> {
    @Override
    public CompletionStage<Void> getBody() {
        return CompletableFuture.completedStage(null);
    }

    @Override
    public void onSubscribe(Flow.Subscription subscription) {
        subscription.cancel();
    }

    @Override
    public void onNext(List<ByteBuffer> item) {}

    @Override
    public void onError(Throwable throwable) {}

    @Override
    public void onComplete() {}
}


// wraps another handler, and only uses it for an expected status
private static HttpResponse.BodyHandler<Void> expectingStatus(int expected, HttpResponse.BodyHandler<Void> handler) {
    return responseInfo -> responseInfo.statusCode() == expected ? handler.apply(responseInfo) : new Unsubscriber();
}

// used like this
Flow.Subscriber<String> subscriber = createSubscriberSomehow();
HttpResponse<Void> response = HttpClient.newHttpClient()
                                        .send(HttpRequest.newBuilder()
                                                         .uri(URI.create("http://example.org/api"))
                                                         .build(),
                                              expectingStatus(200, HttpResponse.BodyHandlers.fromLineSubscriber(subscriber)));
...