/** * Read a single chunk from the given stream. * * @param inputStream to read chunk from * @return a single chunk * @throws IOException if an error occurs while reading the stream */ public ChunkedBodyContents.Chunk readNextChunk(InputStream inputStream) throws IOException { AtomicBoolean hasExtensions = new AtomicBoolean(false); int chunkSize = readChunkSize(inputStream, hasExtensions); if (chunkSize < 0) { throw new IllegalStateException("unexpected EOF, could not read chunked body"); } return readChunk(inputStream, chunkSize, hasExtensions.get()); }
/** * @return this InputStream as an iterator over the chunks of the message body. * <p> * The chunks are consumed lazily. */ public Iterator<ChunkedBodyContents.Chunk> asIterator() { return parser.readLazily(inputStream); }
/** * Parse the full contents of the chunked message. * * @param inputStream to read message from * @param chunkConsumer consumer of individual chunks * @param trailerConsumer consumer of the trailer part * @throws IOException if an error occurs while reading the stream or calling the callbacks */ public void parseChunkedBody(InputStream inputStream, IOConsumer<ChunkedBodyContents.Chunk> chunkConsumer, IOConsumer<RawHttpHeaders> trailerConsumer) throws IOException { int chunkSize = 1; while (chunkSize > 0) { AtomicBoolean hasExtensions = new AtomicBoolean(false); chunkSize = readChunkSize(inputStream, hasExtensions); if (chunkSize < 0) { throw new IllegalStateException("unexpected EOF, could not read chunked body"); } ChunkedBodyContents.Chunk chunk = readChunk(inputStream, chunkSize, hasExtensions.get()); chunkConsumer.accept(chunk); } RawHttpHeaders trailer = readTrailer(inputStream); trailerConsumer.accept(trailer); }
@Override public ChunkedBodyContents.Chunk next() { if (!hasMoreChunks) { throw new NoSuchElementException(); } try { ChunkedBodyContents.Chunk chunk = readNextChunk(inputStream); hasMoreChunks = chunk.size() > 0; if (!hasMoreChunks) { // throw away the trailer-part readTrailer(inputStream); } return chunk; } catch (IOException e) { throw new RuntimeException(e); } } };
/** * Create a new instance of the {@link Chunked} body type. * * @param bodyDecoder the body encoding * @param metadataParser parser for the body trailer part */ public Chunked(BodyDecoder bodyDecoder, HttpMetadataParser metadataParser) { super(bodyDecoder); assert "chunked".equalsIgnoreCase(bodyDecoder.getEncodings().get(bodyDecoder.getEncodings().size() - 1)); this.bodyParser = new ChunkedBodyParser(metadataParser); }
public ChunkedBodyContents getContents(InputStream inputStream) throws IOException { List<ChunkedBodyContents.Chunk> chunks = new ArrayList<>(); AtomicReference<RawHttpHeaders> headersRef = new AtomicReference<>(); bodyParser.parseChunkedBody(inputStream, chunks::add, headersRef::set); return new ChunkedBodyContents(chunks, headersRef.get()); }
boolean hasExtensions) throws IOException { RawHttpHeaders extensions = hasExtensions ? parseExtensions(inputStream) : emptyRawHttpHeaders();
/** * Parse the full contents of the chunked message. * * @param inputStream to read message from * @param chunkConsumer consumer of individual chunks * @param trailerConsumer consumer of the trailer part * @throws IOException if an error occurs while reading the stream or calling the callbacks */ public void parseChunkedBody(InputStream inputStream, IOConsumer<ChunkedBodyContents.Chunk> chunkConsumer, IOConsumer<RawHttpHeaders> trailerConsumer) throws IOException { int chunkSize = 1; while (chunkSize > 0) { AtomicBoolean hasExtensions = new AtomicBoolean(false); chunkSize = readChunkSize(inputStream, hasExtensions); if (chunkSize < 0) { throw new IllegalStateException("unexpected EOF, could not read chunked body"); } ChunkedBodyContents.Chunk chunk = readChunk(inputStream, chunkSize, hasExtensions.get()); chunkConsumer.accept(chunk); } RawHttpHeaders trailer = readTrailer(inputStream); trailerConsumer.accept(trailer); }
@Override public ChunkedBodyContents.Chunk next() { if (!hasMoreChunks) { throw new NoSuchElementException(); } try { ChunkedBodyContents.Chunk chunk = readNextChunk(inputStream); hasMoreChunks = chunk.size() > 0; if (!hasMoreChunks) { // throw away the trailer-part readTrailer(inputStream); } return chunk; } catch (IOException e) { throw new RuntimeException(e); } } };
/** * Create a new instance of the {@link Chunked} body type. * * @param bodyDecoder the body encoding * @param metadataParser parser for the body trailer part */ public Chunked(BodyDecoder bodyDecoder, HttpMetadataParser metadataParser) { super(bodyDecoder); assert "chunked".equalsIgnoreCase(bodyDecoder.getEncodings().get(bodyDecoder.getEncodings().size() - 1)); this.bodyParser = new ChunkedBodyParser(metadataParser); }
@Override public void consumeDataInto(InputStream inputStream, OutputStream out, int bufferSize) throws IOException { bodyParser.parseChunkedBody(inputStream, chunk -> out.write(chunk.getData()), trailer -> { // ignore trailer }); }
boolean hasExtensions) throws IOException { RawHttpHeaders extensions = hasExtensions ? parseExtensions(inputStream) : emptyRawHttpHeaders();
/** * Read the next chunk available from the source input stream. * <p> * The last chunk is always the empty chunk. After the empty chunk is returned, the message is completed * and calling this method again after that results in an {@link IllegalStateException}. * <p> * When the last chunk is returned, the trailer-part, if any, is also consumed and can be obtained by * calling the {@link InputStreamChunkDecoder#getTrailer()} method. * * @return the next chunk * @throws IOException if an error occurs while reading the original stream * @throws IllegalStateException if this method is called after the empty chunk is returned */ public ChunkedBodyContents.Chunk readChunk() throws IOException { if (done) { throw new IllegalStateException("HTTP message body is already consumed"); } ChunkedBodyContents.Chunk chunk = parser.readNextChunk(inputStream); if (chunk.size() == 0) { trailer = parser.readTrailer(inputStream); done = true; currentSource = null; } else { currentSource = new ByteArrayInputStream(chunk.getData()); } return chunk; }
/** * Read a single chunk from the given stream. * * @param inputStream to read chunk from * @return a single chunk * @throws IOException if an error occurs while reading the stream */ public ChunkedBodyContents.Chunk readNextChunk(InputStream inputStream) throws IOException { AtomicBoolean hasExtensions = new AtomicBoolean(false); int chunkSize = readChunkSize(inputStream, hasExtensions); if (chunkSize < 0) { throw new IllegalStateException("unexpected EOF, could not read chunked body"); } return readChunk(inputStream, chunkSize, hasExtensions.get()); }
new ChunkedBodyParser(createStrictHttpMetadataParser()), responseStream);
public ChunkedBodyContents getContents(InputStream inputStream) throws IOException { List<ChunkedBodyContents.Chunk> chunks = new ArrayList<>(); AtomicReference<RawHttpHeaders> headersRef = new AtomicReference<>(); bodyParser.parseChunkedBody(inputStream, chunks::add, headersRef::set); return new ChunkedBodyContents(chunks, headersRef.get()); }
/** * Consume the given stream lazily, one chunk at a time. * <p> * The last chunk is always the empty chunk, so once the empty chunk is received, * trying to consume another chunk will result in an error. * * @param inputStream supplying a chunked body * @return lazy iterator of chunks */ public Iterator<ChunkedBodyContents.Chunk> consumeLazily(InputStream inputStream) { return bodyParser.readLazily(inputStream); }
/** * Read the next chunk available from the source input stream. * <p> * The last chunk is always the empty chunk. After the empty chunk is returned, the message is completed * and calling this method again after that results in an {@link IllegalStateException}. * <p> * When the last chunk is returned, the trailer-part, if any, is also consumed and can be obtained by * calling the {@link InputStreamChunkDecoder#getTrailer()} method. * * @return the next chunk * @throws IOException if an error occurs while reading the original stream * @throws IllegalStateException if this method is called after the empty chunk is returned */ public ChunkedBodyContents.Chunk readChunk() throws IOException { if (done) { throw new IllegalStateException("HTTP message body is already consumed"); } ChunkedBodyContents.Chunk chunk = parser.readNextChunk(inputStream); if (chunk.size() == 0) { trailer = parser.readTrailer(inputStream); done = true; currentSource = null; } else { currentSource = new ByteArrayInputStream(chunk.getData()); } return chunk; }
@Override public void consumeDataInto(InputStream inputStream, OutputStream out, int bufferSize) throws IOException { bodyParser.parseChunkedBody(inputStream, chunk -> out.write(chunk.getData()), trailer -> { // ignore trailer }); }
/** * @return this InputStream as an iterator over the chunks of the message body. * <p> * The chunks are consumed lazily. */ public Iterator<ChunkedBodyContents.Chunk> asIterator() { return parser.readLazily(inputStream); }