Interface Content.Source

All Known Subinterfaces:
Request, Request.Content, Request.ServeAs, ServerUpgradeRequest, ServerUpgradeRequest
All Known Implementing Classes:
AsyncContent, AsyncRequestContent, ByteBufferContentSource, ByteBufferRequestContent, BytesRequestContent, ChunksContentSource, ContentSourceRequestContent, ContentSourceTransformer, ContextRequest, ErrorHandler.ErrorRequest, FormRequestContent, GzipRequest, HeaderWrappingRequest, HttpChannelState.ChannelRequest, InputStreamContentSource, InputStreamRequestContent, MultiPart.AbstractContentSource, MultiPartByteRanges.ContentSource, MultiPartByteRanges.InputStreamContentSource, MultiPartByteRanges.PathContentSource, MultiPartFormData.ContentSource, MultiPartRequestContent, OutputStreamContentSource, OutputStreamRequestContent, PathContentSource, PathRequestContent, ProxyHandler.ProxyRequestContent, ProxyServlet.ProxyInputStreamRequestContent, Request.AttributesWrapper, Request.Wrapper, Rule.Handler, Rule.HttpURIHandler, SecureRequestCustomizer.SecureRequest, SecureRequestCustomizer.SecureRequestWithSslSessionData, ServerUpgradeRequestDelegate, ServerUpgradeRequestImpl, ServletContextRequest, ServletCoreRequest, StatisticsHandler.MinimumDataRateHandler.MinimumDataRateRequest, StringRequestContent
Enclosing class:
Content

public static interface Content.Source

A source of content that can be read with a read/demand model.

To avoid leaking its resources, a source must either:

  • be read until it returns a last chunk, either EOF or a terminal failure
  • be failed

Idiomatic usage

The read/demand model typical usage is the following:


 public void onContentAvailable() {
     while (true) {
         // Read a chunk
         Chunk chunk = source.read();

         // There is no chunk, demand to be called back and exit.
         if (chunk == null) {
             source.demand(this::onContentAvailable);
             return;
         }

         // The chunk is a failure.
         if (Content.Chunk.isFailure(chunk))
         {
             boolean fatal = chunk.isLast();
             if (fatal)
             {
                 handleFatalFailure(chunk.getFailure());
                 return;
             }
             else
             {
                 handleTransientFailure(chunk.getFailure());
                 continue;
             }
         }

         // It's a valid chunk, consume the chunk's bytes.
         ByteBuffer buffer = chunk.getByteBuffer();
         // ...

         // Release the chunk when it has been consumed.
         chunk.release();

         // Exit if the Content.Source is fully consumed.
         if (chunk.isLast())
             break;
     }
 }
 
  • Method Details

    • asByteBuffer

      static void asByteBuffer(Content.Source source, Promise<ByteBuffer> promise)

      Reads, non-blocking, the whole content source into a ByteBuffer.

      Parameters:
      source - the source to read
      promise - the promise to notify when the whole content has been read into a ByteBuffer.
    • asByteBuffer

      static ByteBuffer asByteBuffer(Content.Source source) throws IOException

      Reads, blocking if necessary, the whole content source into a ByteBuffer.

      Parameters:
      source - the source to read
      Returns:
      the ByteBuffer containing the content
      Throws:
      IOException - if reading the content fails
    • asByteArrayAsync

      static CompletableFuture<byte[]> asByteArrayAsync(Content.Source source, int maxSize)

      Reads, non-blocking, the whole content source into a byte array.

      Parameters:
      source - the source to read
      maxSize - The maximum size to read, or -1 for no limit
      Returns:
      A CompletableFuture that will be completed when the complete content is read or failed if the max size is exceeded or there is a read error.
    • asByteBufferAsync

      static CompletableFuture<ByteBuffer> asByteBufferAsync(Content.Source source)

      Reads, non-blocking, the whole content source into a ByteBuffer.

      Parameters:
      source - the source to read
      Returns:
      the CompletableFuture to notify when the whole content has been read
    • asByteBufferAsync

      static CompletableFuture<ByteBuffer> asByteBufferAsync(Content.Source source, int maxSize)

      Reads, non-blocking, the whole content source into a ByteBuffer.

      Parameters:
      source - the source to read
      maxSize - The maximum size to read, or -1 for no limit
      Returns:
      the CompletableFuture to notify when the whole content has been read
    • asRetainableByteBuffer

      static CompletableFuture<RetainableByteBuffer> asRetainableByteBuffer(Content.Source source, ByteBufferPool pool, boolean direct, int maxSize)

      Reads, non-blocking, the whole content source into a RetainableByteBuffer.

      Parameters:
      source - The Content.Source to read
      pool - The ByteBufferPool to acquire the buffer from, or null for a non Retainable buffer
      direct - True if the buffer should be direct.
      maxSize - The maximum size to read, or -1 for no limit
      Returns:
      A CompletableFuture that will be completed when the complete content is read or failed if the max size is exceeded or there is a read error.
    • asString

      static void asString(Content.Source source, Charset charset, Promise<String> promise)

      Reads, non-blocking, the whole content source into a String, converting the bytes using the given Charset.

      Parameters:
      source - the source to read
      charset - the charset to use to convert the bytes into characters
      promise - the promise to notify when the whole content has been converted into a String
    • asString

      static String asString(Content.Source source) throws IOException

      Reads, blocking if necessary, the whole content source into a String, converting the bytes using UTF-8.

      Parameters:
      source - the source to read
      Returns:
      the String obtained from the content
      Throws:
      IOException - if reading the content fails
    • asString

      static String asString(Content.Source source, Charset charset) throws IOException

      Reads, blocking if necessary, the whole content source into a String, converting the bytes using the given Charset.

      Parameters:
      source - the source to read
      charset - the charset to use to decode bytes
      Returns:
      the String obtained from the content
      Throws:
      IOException - if reading the content fails
    • asStringAsync

      static CompletableFuture<String> asStringAsync(Content.Source source, Charset charset)

      Read, non-blocking, the whole content source into a String, converting the bytes using the given Charset.

      Parameters:
      source - the source to read
      charset - the charset to use to decode bytes
      Returns:
      the CompletableFuture to notify when the whole content has been read
    • asInputStream

      static InputStream asInputStream(Content.Source source)

      Wraps the given content source with an InputStream.

      Parameters:
      source - the source to read from
      Returns:
      an InputStream that reads from the content source
    • asPublisher

      static Flow.Publisher<Content.Chunk> asPublisher(Content.Source source)

      Wraps the given content source with a Flow.Publisher.

      Parameters:
      source - the source to read from
      Returns:
      a Publisher that publishes chunks read from the content source
    • consumeAll

      static void consumeAll(Content.Source source, Callback callback)

      Reads, non-blocking, the given content source, until a failure or EOF and discards the content.

      Parameters:
      source - the source to read from
      callback - the callback to notify when the whole content has been read or a failure occurred while reading the content
    • consumeAll

      static void consumeAll(Content.Source source) throws IOException

      Reads, blocking if necessary, the given content source, until a failure or EOF, and discards the content.

      Parameters:
      source - the source to read from
      Throws:
      IOException - if reading the content fails
    • getLength

      default long getLength()
      Returns:
      the content length, if known, or -1 if the content length is unknown
    • read

      Reads a chunk of content.

      See how to use this method idiomatically.

      The returned chunk could be:

      • null, to signal that there isn't a chunk of content available
      • an Content.Chunk instance with non null Content.Chunk.getFailure(), to signal that there was a failure trying to produce a chunk of content, or that the content production has been failed externally
      • a Content.Chunk instance, containing the chunk of content.

      Once a read returns an Content.Chunk instance with non-null Content.Chunk.getFailure() then if the failure is last further reads will continue to return the same failure chunk instance, otherwise further read() operations may return different non-failure chunks.

      Once a read returns a last chunk, further reads will continue to return a last chunk (although the instance may be different).

      The content reader code must ultimately arrange for a call to Retainable.release() on the returned Content.Chunk.

      Additionally, prior to the ultimate call to Retainable.release(), the reader code may make additional calls to Retainable.retain(), that must ultimately be matched by a correspondent number of calls to Retainable.release().

      Concurrent reads from different threads are not recommended, as they are inherently in a race condition.

      Reads performed outside the invocation context of a demand callback are allowed. However, reads performed with a pending demand are inherently in a race condition (the thread that reads with the thread that invokes the demand callback).

      Returns:
      a chunk of content, possibly a failure instance, or null
      See Also:
    • demand

      void demand(Runnable demandCallback)

      Demands to invoke the given demand callback parameter when a chunk of content is available.

      See how to use this method idiomatically.

      Implementations guarantee that calls to this method are safely reentrant so that stack overflows are avoided in the case of mutual recursion between the execution of the Runnable callback and a call to this method. Invocations of the passed Runnable are serialized and a callback for demand call is not invoked until any previous demand callback has returned. Thus the Runnable should not block waiting for a callback of a future demand call.

      The demand callback may be invoked spuriously: a subsequent call to read() may return null.

      Calling this method establishes a pending demand, which is fulfilled when the demand callback is invoked.

      Calling this method when there is already a pending demand results in an IllegalStateException to be thrown.

      If the invocation of the demand callback throws an exception, then fail(Throwable) is called.

      Parameters:
      demandCallback - the demand callback to invoke where there is a content chunk available
      Throws:
      IllegalStateException - when this method is called with an existing demand
      See Also:
    • fail

      void fail(Throwable failure)

      Fails this content source with a last failure chunk, failing and discarding accumulated content chunks that were not yet read.

      The failure may be notified to the content reader at a later time, when the content reader reads a content chunk, via a Content.Chunk instance with a non null Content.Chunk.getFailure().

      If read() has returned a last chunk, this is a no operation.

      Typical failure: the content being aborted by user code, or idle timeouts.

      If this method has already been called, then it is a no operation.

      Parameters:
      failure - the cause of the failure
      See Also:
    • fail

      default void fail(Throwable failure, boolean last)

      Fails this content source with a failure chunk that may or not may be last. If last is true, then the failure is persistent and a call to this method acts as fail(Throwable). Otherwise the failure is transient and a failure chunk will be read in order with content chunks, and subsequent calls to read may produce other content.

      A Content.Source or its reader may treat a transient failure as persistent.

      Parameters:
      failure - A failure.
      last - true if the failure is persistent, false if the failure is transient.
      See Also:
    • rewind

      default boolean rewind()

      Rewinds this content, if possible, so that subsequent reads return chunks starting from the beginning of this content.

      Returns:
      true if this content has been rewound, false if this content cannot be rewound