Class HttpResponse.BodySubscribers
- Enclosing interface:
HttpResponse<T>
BodySubscriber
that implement
various useful subscribers, such as converting the response body bytes
into a String, or streaming the bytes to a file.
The following are examples of using the predefined body subscribers to convert a flow of response body data into common high-level Java objects:
// Streams the response body to a File
HttpResponse<Path> response = client
.send(request, responseInfo -> BodySubscribers.ofFile(Paths.get("example.html"));
// Accumulates the response body and returns it as a byte[]
HttpResponse<byte[]> response = client
.send(request, responseInfo -> BodySubscribers.ofByteArray());
// Discards the response body
HttpResponse<Void> response = client
.send(request, responseInfo -> BodySubscribers.discarding());
// Accumulates the response body as a String then maps it to its bytes
HttpResponse<byte[]> response = client
.send(request, responseInfo ->
BodySubscribers.mapping(BodySubscribers.ofString(UTF_8), String::getBytes));
- API Note:
Some body implementations created by body subscribers may allow response bytes to be streamed to the caller. These implementations are typically
AutoCloseable
and may need to be explicitly closed in order for the resources associated with the request and the client to be eventually reclaimed. Some other implementations are publishers which need to besubscribed
in order for their associated resources to be released and for the associated request to run to completion.- Since:
- 11
-
Method Summary
Modifier and TypeMethodDescriptionstatic <T> HttpResponse.BodySubscriber
<T> buffering
(HttpResponse.BodySubscriber<T> downstream, int bufferSize) Returns aBodySubscriber
which buffers data before delivering it to the given downstream subscriber.static HttpResponse.BodySubscriber
<Void> Returns a response subscriber which discards the response body.static HttpResponse.BodySubscriber
<Void> fromLineSubscriber
(Flow.Subscriber<? super String> subscriber) Returns a body subscriber that forwards all response body to the givenFlow.Subscriber
, line by line.static <S extends Flow.Subscriber<? super String>, T>
HttpResponse.BodySubscriber<T> fromLineSubscriber
(S subscriber, Function<? super S, ? extends T> finisher, Charset charset, String lineSeparator) Returns a body subscriber that forwards all response body to the givenFlow.Subscriber
, line by line.static HttpResponse.BodySubscriber
<Void> fromSubscriber
(Flow.Subscriber<? super List<ByteBuffer>> subscriber) Returns a body subscriber that forwards all response body to the givenFlow.Subscriber
.static <S extends Flow.Subscriber<? super List<ByteBuffer>>, T>
HttpResponse.BodySubscriber<T> fromSubscriber
(S subscriber, Function<? super S, ? extends T> finisher) Returns a body subscriber that forwards all response body to the givenFlow.Subscriber
.static <T,
U> HttpResponse.BodySubscriber <U> mapping
(HttpResponse.BodySubscriber<T> upstream, Function<? super T, ? extends U> mapper) Returns aBodySubscriber
whose response body value is that of the result of applying the given function to the body object of the givenupstream
BodySubscriber
.static HttpResponse.BodySubscriber
<byte[]> Returns aBodySubscriber
which stores the response body as a byte array.static HttpResponse.BodySubscriber
<Void> ofByteArrayConsumer
(Consumer<Optional<byte[]>> consumer) Returns aBodySubscriber
which provides the incoming body data to the provided Consumer ofOptional<byte[]>
.static HttpResponse.BodySubscriber
<Path> Returns aBodySubscriber
which stores the response body in a file opened with the given name.static HttpResponse.BodySubscriber
<Path> ofFile
(Path file, OpenOption... openOptions) Returns aBodySubscriber
which stores the response body in a file opened with the given options and name.Returns aBodySubscriber
which streams the response body as anInputStream
.static HttpResponse.BodySubscriber
<Stream<String>> Returns aBodySubscriber
which streams the response body as aStream
<String>
, where each string in the stream corresponds to a line as defined byBufferedReader.lines()
.Returns a response subscriber which publishes the response body through aPublisher<List<ByteBuffer>>
.static HttpResponse.BodySubscriber
<String> Returns a body subscriber which stores the response body as aString
converted using the givenCharset
.static <U> HttpResponse.BodySubscriber
<U> replacing
(U value) Returns a response subscriber which discards the response body.
-
Method Details
-
fromSubscriber
public static HttpResponse.BodySubscriber<Void> fromSubscriber(Flow.Subscriber<? super List<ByteBuffer>> subscriber) Returns a body subscriber that forwards all response body to the givenFlow.Subscriber
. The completion stage of the returned body subscriber completes after one of the given subscribersonComplete
oronError
has been invoked.- API Note:
- This method can be used as an adapter between
BodySubscriber
andFlow.Subscriber
. - Parameters:
subscriber
- the subscriber- Returns:
- a body subscriber
-
fromSubscriber
public static <S extends Flow.Subscriber<? super List<ByteBuffer>>, T> HttpResponse.BodySubscriber<T> fromSubscriber(S subscriber, Function<? super S, ? extends T> finisher) Returns a body subscriber that forwards all response body to the givenFlow.Subscriber
. The completion stage of the returned body subscriber completes after one of the given subscribersonComplete
oronError
has been invoked.The given
finisher
function is applied after the given subscriber'sonComplete
has been invoked. Thefinisher
function is invoked with the given subscriber, and returns a value that is set as the response's body.- API Note:
- This method can be used as an adapter between
BodySubscriber
andFlow.Subscriber
. - Type Parameters:
S
- the type of the SubscriberT
- the type of the response body- Parameters:
subscriber
- the subscriberfinisher
- a function to be applied after the subscriber has completed- Returns:
- a body subscriber
-
fromLineSubscriber
public static HttpResponse.BodySubscriber<Void> fromLineSubscriber(Flow.Subscriber<? super String> subscriber) Returns a body subscriber that forwards all response body to the givenFlow.Subscriber
, line by line. The completion stage of the returned body subscriber completes after one of the given subscribersonComplete
oronError
has been invoked. Bytes are decoded using theUTF-8
charset, and lines are delimited in the manner ofBufferedReader.readLine()
.- API Note:
- This method can be used as an adapter between
BodySubscriber
andFlow.Subscriber
. - Implementation Note:
- This is equivalent to calling
fromLineSubscriber(subscriber, s -> null, StandardCharsets.UTF_8, null)
- Parameters:
subscriber
- the subscriber- Returns:
- a body subscriber
-
fromLineSubscriber
public static <S extends Flow.Subscriber<? super String>, T> HttpResponse.BodySubscriber<T> fromLineSubscriber(S subscriber, Function<? super S, ? extends T> finisher, Charset charset, String lineSeparator) Returns a body subscriber that forwards all response body to the givenFlow.Subscriber
, line by line. The completion stage of the returned body subscriber completes after one of the given subscribersonComplete
oronError
has been invoked.The given
finisher
function is applied after the given subscriber'sonComplete
has been invoked. Thefinisher
function is invoked with the given subscriber, and returns a value that is set as the response's body.- API Note:
- This method can be used as an adapter between
BodySubscriber
andFlow.Subscriber
. - Type Parameters:
S
- the type of the SubscriberT
- the type of the response body- Parameters:
subscriber
- the subscriberfinisher
- a function to be applied after the subscriber has completedcharset
- aCharset
to decode the byteslineSeparator
- an optional line separator: can benull
, in which case lines will be delimited in the manner ofBufferedReader.readLine()
.- Returns:
- a body subscriber
- Throws:
IllegalArgumentException
- if the suppliedlineSeparator
is the empty string
-
ofString
Returns a body subscriber which stores the response body as aString
converted using the givenCharset
.The
HttpResponse
using this subscriber is available after the entire response has been read.- Parameters:
charset
- the character set to convert the String with- Returns:
- a body subscriber
-
ofByteArray
Returns aBodySubscriber
which stores the response body as a byte array.The
HttpResponse
using this subscriber is available after the entire response has been read.- Returns:
- a body subscriber
-
ofFile
Returns aBodySubscriber
which stores the response body in a file opened with the given options and name. The file will be opened with the given options usingFileChannel.open
just before the body is read. Any exception thrown will be returned or thrown fromHttpClient::send
orHttpClient::sendAsync
as appropriate.The
HttpResponse
using this subscriber is available after the entire response has been read.- Parameters:
file
- the file to store the body inopenOptions
- the list of options to open the file with- Returns:
- a body subscriber
- Throws:
IllegalArgumentException
- if an invalid set of open options are specified
-
ofFile
Returns aBodySubscriber
which stores the response body in a file opened with the given name.Equivalent to:
ofFile(file, CREATE, WRITE)
- Parameters:
file
- the file to store the body in- Returns:
- a body subscriber
-
ofByteArrayConsumer
public static HttpResponse.BodySubscriber<Void> ofByteArrayConsumer(Consumer<Optional<byte[]>> consumer) Returns aBodySubscriber
which provides the incoming body data to the provided Consumer ofOptional<byte[]>
. Each call toConsumer.accept()
will contain a non emptyOptional
, except for the final invocation after all body data has been read, when theOptional
will be empty.The
HttpResponse
using this subscriber is available after the entire response has been read.- API Note:
- This subscriber is not flow controlled. Therefore, the supplied consumer must be able to process whatever amount of data is delivered in a timely fashion.
- Parameters:
consumer
- a Consumer of byte arrays- Returns:
- a body subscriber
-
ofInputStream
Returns aBodySubscriber
which streams the response body as anInputStream
.The
HttpResponse
using this subscriber is available immediately after the response headers have been read, without requiring to wait for the entire body to be processed. The response body can then be read directly from theInputStream
.- API Note:
- To ensure that all resources associated with the
corresponding exchange are properly released the caller must
ensure to either read all bytes until EOF is reached, or call
InputStream.close()
if it is unable or unwilling to do so. Callingclose
before exhausting the stream may cause the underlying HTTP connection to be closed and prevent it from being reused for subsequent operations. - Implementation Note:
- The
read
method of theInputStream
returned by the default implementation of this method will throw anIOException
with the thread interrupt status set if the thread is interrupted while blocking on read. In that case, the request will also be cancelled and theInputStream
will be closed. - Returns:
- a streaming body subscriber
which streams the response body as an
InputStream
.
-
ofLines
Returns aBodySubscriber
which streams the response body as aStream
<String>
, where each string in the stream corresponds to a line as defined byBufferedReader.lines()
.The
HttpResponse
using this subscriber is available immediately after the response headers have been read, without requiring to wait for the entire body to be processed. The response body can then be read directly from theStream
.- API Note:
- To ensure that all resources associated with the
corresponding exchange are properly released the caller must
ensure to either read all lines until the stream is exhausted,
or call
BaseStream.close()
if it is unable or unwilling to do so. Callingclose
before exhausting the stream may cause the underlying HTTP connection to be closed and prevent it from being reused for subsequent operations. - Parameters:
charset
- the character set to use when converting bytes to characters- Returns:
- a streaming body subscriber which streams
the response body as a
Stream
<String>
. - See Also:
-
ofPublisher
Returns a response subscriber which publishes the response body through aPublisher<List<ByteBuffer>>
.The
HttpResponse
using this subscriber is available immediately after the response headers have been read, without requiring to wait for the entire body to be processed. The response body bytes can then be obtained by subscribing to the publisher returned by theHttpResponse
body
method.The publisher returned by the
body
method can be subscribed to only once. The first subscriber will receive the body response bytes if successfully subscribed, or will cause the subscription to be cancelled otherwise. If more subscriptions are attempted, the subsequent subscribers will be immediately subscribed with an empty subscription and theironError
method will be invoked with anIllegalStateException
.- API Note:
- To ensure that all resources associated with the
corresponding exchange are properly released the caller must
ensure that the provided publisher is subscribed once, and either
requests all bytes
until
onComplete
oronError
are invoked, or cancel the provided subscription if it is unable or unwilling to do so. Note that depending on the actual HTTP protocol version used for the exchange, cancelling the subscription instead of exhausting the flow may cause the underlying HTTP connection to be closed and prevent it from being reused for subsequent operations. - Returns:
- A publishing body subscriber
which publishes the response body
through a
Publisher<List<ByteBuffer>>
.
-
replacing
Returns a response subscriber which discards the response body. The supplied value is the value that will be returned fromHttpResponse.body()
.- Type Parameters:
U
- the type of the response body- Parameters:
value
- the value to return from HttpResponse.body(), may benull
- Returns:
- a body subscriber
-
discarding
Returns a response subscriber which discards the response body.- Returns:
- a response body subscriber
-
buffering
public static <T> HttpResponse.BodySubscriber<T> buffering(HttpResponse.BodySubscriber<T> downstream, int bufferSize) Returns aBodySubscriber
which buffers data before delivering it to the given downstream subscriber. The subscriber guarantees to deliverbufferSize
bytes of data to each invocation of the downstream'sonNext
method, except for the final invocation, just beforeonComplete
is invoked. The final invocation ofonNext
may contain fewer thanbufferSize
bytes.The returned subscriber delegates its
getBody()
method to the downstream subscriber.- Type Parameters:
T
- the type of the response body- Parameters:
downstream
- the downstream subscriberbufferSize
- the buffer size- Returns:
- a buffering body subscriber
- Throws:
IllegalArgumentException
- ifbufferSize <= 0
-
mapping
public static <T,U> HttpResponse.BodySubscriber<U> mapping(HttpResponse.BodySubscriber<T> upstream, Function<? super T, ? extends U> mapper) Returns aBodySubscriber
whose response body value is that of the result of applying the given function to the body object of the givenupstream
BodySubscriber
.The mapping function is executed using the client's executor, and can therefore be used to map any response body type, including blocking
InputStream
. However, performing any blocking operation in the mapper function runs the risk of blocking the executor's thread for an unknown amount of time (at least until the blocking operation finishes), which may end up starving the executor of available threads. Therefore, in the case where mapping to the desired type might block (e.g. by reading on theInputStream
), then mapping to aSupplier
of the desired type and deferring the blocking operation untilSupplier::get
is invoked by the caller's thread should be preferred, as shown in the following example which uses a well-known JSON parser to convert anInputStream
into any annotated Java type.For example:
public static <W> BodySubscriber<Supplier<W>> asJSON(Class<W> targetType) { BodySubscriber<InputStream> upstream = BodySubscribers.ofInputStream(); BodySubscriber<Supplier<W>> downstream = BodySubscribers.mapping( upstream, (InputStream is) -> () -> { try (InputStream stream = is) { ObjectMapper objectMapper = new ObjectMapper(); return objectMapper.readValue(stream, targetType); } catch (IOException e) { throw new UncheckedIOException(e); } }); return downstream; }
- Type Parameters:
T
- the upstream body typeU
- the type of the body subscriber returned- Parameters:
upstream
- the body subscriber to be mappedmapper
- the mapping function- Returns:
- a mapping body subscriber
-