Streaming Requests¶
MoreBodyPublishers
provides publishers for asynchronously streaming the request body into an OutputStream
or a WritableByteChannel
.
Let's say your sever supports compressed requests. If you're sending a large file, you might want to send it in gzip.
final Methanol client = Methanol.create();
final Executor executor = Executors.newVirtualThreadPerTaskExecutor();
HttpResponse<Void> postGzipped(Path file) {
return client.send(
MutableRequest.POST(
"https://example.com",
MoreBodyPublishers.ofOutputStream(
out -> Files.copy(file, out), executor))
.header("Content-Encoding", "gzip"),
BodyHandlers.discarding());
}
MoreBodyPublishers::ofOutputStream
accepts a callback that takes the OutputStream
to stream to. The callback is invoked on the given executor.
The stream buffers written content in case the consumer (HTTP client) can't keep up with the producer (the publisher). In such case, consumed memory is bounded by blocking the writer as long as the size of unconsumed data is hitting a certain threshold, which is computed as:
int memoryQuota = Integer.getInteger("com.github.mizosoft.methanol.flow.prefetch", 8) * Integer.getInteger("jdk.httpclient.bufsize", 16 * 1024);
The stream may also buffer content temporarily til an inner buffer (with size Integer.getInteger("jdk.httpclient.bufsize", 16 * 1024)
) becomes full. You can use OutputStream::flush
to make such content immediately available for consumption.
The stream is closed automatically after the callback. If the callback fails, the request is completed exceptionally.
As of 1.8.0, this is the recommended way for streaming requests rather than using WritableBodyPublisher
directly.