0

I want to have a send a request body generating the body a piece at a time, but without knowing the entire length ahead of time. In other words, I need to send a chunked request.

I can't find how to do this.

The main distinction between two types of connections is inability to use the usual, but inherently blocking java.io.InputStream and java.io.OutputStream classes to represent streams of inbound and outbound content. HttpCore NIO provides ContentEncoder and ContentDecoder interfaces to handle the process of asynchronous content transfer.

...

Non-blocking HTTP connections will fire output events until the content entity is marked as fully transferred.

ContentEncoder encoder = <...>
// Prepare output data
ByteBuffer src = ByteBuffer.allocate(2048);
// Write data out
encoder.write(src);
// Mark content entity as fully transferred when done
encoder.complete();

I looked at org.apache.http.nio.conn.ClientAsyncConnection, but I can't see where the output events are being fired.

I can find examples for sending files, but none for the content generation that I want to do.

How do I send a streaming, chunked request with the AsyncHttpClient?

Community
  • 1
  • 1
Paul Draper
  • 78,542
  • 46
  • 206
  • 285

1 Answers1

0

You could implement a custom HttpAsyncRequestProducer and make it stream out content either using one of the provided HttpAsyncContentProducer or implement your own content generation logic

public class MyAsyncRequestProducer implements HttpAsyncRequestProducer {

    private final HttpHost target;
    private final HttpAsyncContentProducer producer;

    public MyAsyncRequestProducer(
            final HttpHost target,
            final HttpAsyncContentProducer producer) {
        super();
        Args.notNull(target, "HTTP host");
        Args.notNull(producer, "HTTP content producer");
        this.target = target;
        this.producer = producer;
    }

    public synchronized HttpRequest generateRequest() {
        BasicHttpEntityEnclosingRequest request = new BasicHttpEntityEnclosingRequest("POST", "/");
        BasicHttpEntity entity = new BasicHttpEntity();
        entity.setContentType(ContentType.TEXT_PLAIN.toString());
        entity.setContentLength(-1);
        entity.setChunked(true);
        request.setEntity(entity);
        return request;
    }

    public HttpHost getTarget() {
        return this.target;
    }

    public synchronized void produceContent(
            final ContentEncoder encoder, final IOControl ioctrl) throws IOException {
        this.producer.produceContent(encoder, ioctrl);
        if (encoder.isCompleted()) {
            this.producer.close();
        }
    }

    public void requestCompleted(final HttpContext context) {
    }

    public void failed(final Exception ex) {
    }

    public synchronized boolean isRepeatable() {
        return this.producer.isRepeatable();
    }

    public synchronized void resetRequest() throws IOException {
        this.producer.close();
    }

    public synchronized void close() throws IOException {
        this.producer.close();
    }

}
ok2c
  • 26,450
  • 5
  • 63
  • 71