/** * Read some bytes from the stream. * @param b The byte array that will hold the contents from the stream. * @return The number of bytes returned or -1 if the end of stream has been * reached. * @throws IOException in case of an I/O error */ @Override public int read (final byte[] b) throws IOException { return read(b, 0, b.length); }
/** * Read the next chunk. * @throws IOException in case of an I/O error */ private void nextChunk() throws IOException { if (state == State.CHUNK_INVALID) { throw new MalformedChunkCodingException("Corrupt data stream"); } try { chunkSize = getChunkSize(); if (chunkSize < 0L) { throw new MalformedChunkCodingException("Negative chunk size"); } state = State.CHUNK_DATA; pos = 0L; if (chunkSize == 0L) { eof = true; parseTrailerHeaders(); } } catch (final MalformedChunkCodingException ex) { state = State.CHUNK_INVALID; throw ex; } }
@Test(expected = MalformedChunkCodingException.class) public void testCorruptChunkedInputStreamInvalidFooter() throws IOException { final String s = "1\r\n0\r\n0\r\nstuff\r\n"; final SessionInputBuffer inBuffer = new SessionInputBufferImpl(16); final ByteArrayInputStream inputStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.ISO_8859_1)); final ChunkedInputStream in = new ChunkedInputStream(inBuffer, inputStream); in.read(); in.read(); in.close(); }
@Test public void testChunkedInputStreamSmallBuffer() throws IOException { final SessionInputBuffer inBuffer = new SessionInputBufferImpl(16); final ByteArrayInputStream inputStream = new ByteArrayInputStream(CHUNKED_INPUT.getBytes(StandardCharsets.ISO_8859_1)); final ChunkedInputStream in = new ChunkedInputStream(inBuffer, inputStream); final byte[] buffer = new byte[7]; final ByteArrayOutputStream out = new ByteArrayOutputStream(); int len; while ((len = in.read(buffer)) > 0) { out.write(buffer, 0, len); } Assert.assertEquals(-1, in.read(buffer)); Assert.assertEquals(-1, in.read(buffer)); in.close(); final Header[] footers = in.getFooters(); Assert.assertNotNull(footers); Assert.assertEquals(2, footers.length); Assert.assertEquals("Footer1", footers[0].getName()); Assert.assertEquals("abcde", footers[0].getValue()); Assert.assertEquals("Footer2", footers[1].getName()); Assert.assertEquals("fghij", footers[1].getValue()); }
@Test public void testAvailable() throws IOException { final String s = "5\r\n12345\r\n0\r\n"; final SessionInputBuffer inBuffer = new SessionInputBufferImpl(16); final ByteArrayInputStream inputStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.ISO_8859_1)); final ChunkedInputStream in = new ChunkedInputStream(inBuffer, inputStream); Assert.assertEquals(0, in.available()); in.read(); Assert.assertEquals(4, in.available()); in.close(); }
@Test public void testHugeChunk() throws IOException { final SessionInputBuffer inBuffer = new SessionInputBufferImpl(16); final ByteArrayInputStream inputStream = new ByteArrayInputStream("1234567890abcdef\r\n01234567".getBytes( StandardCharsets.ISO_8859_1)); final ChunkedInputStream in = new ChunkedInputStream(inBuffer, inputStream); final ByteArrayOutputStream out = new ByteArrayOutputStream(); for (int i = 0; i < 8; ++i) { out.write(in.read()); } final String result = new String(out.toByteArray(), StandardCharsets.ISO_8859_1); Assert.assertEquals("01234567", result); }
protected InputStream createContentInputStream( final long len, final SessionInputBuffer buffer, final InputStream inputStream) { if (len > 0) { return new ContentLengthInputStream(buffer, inputStream, len); } else if (len == 0) { return EmptyInputStream.INSTANCE; } else if (len == ContentLengthStrategy.CHUNKED) { return new ChunkedInputStream(buffer, inputStream, this.h1Config); } else { return new IdentityInputStream(buffer, inputStream); } }
nextChunk(); if (this.eof) { return -1;
@Test(expected=ConnectionClosedException.class) public void testChunkedInputStreamNoClosingChunk() throws IOException { final String s = "5\r\n01234\r\n"; final SessionInputBuffer inBuffer = new SessionInputBufferImpl(16); final ByteArrayInputStream inputStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.ISO_8859_1)); final ChunkedInputStream in = new ChunkedInputStream(inBuffer, inputStream); final byte[] tmp = new byte[5]; Assert.assertEquals(5, in.read(tmp)); in.read(); in.close(); }
@Test public void testChunkedInputStreamLargeBuffer() throws IOException { final SessionInputBuffer inBuffer = new SessionInputBufferImpl(16); final ByteArrayInputStream inputStream = new ByteArrayInputStream(CHUNKED_INPUT.getBytes(StandardCharsets.ISO_8859_1)); final ChunkedInputStream in = new ChunkedInputStream(inBuffer, inputStream); final byte[] buffer = new byte[300]; final ByteArrayOutputStream out = new ByteArrayOutputStream(); int len; while ((len = in.read(buffer)) > 0) { out.write(buffer, 0, len); } Assert.assertEquals(-1, in.read(buffer)); Assert.assertEquals(-1, in.read(buffer)); in.close(); final String result = new String(out.toByteArray(), StandardCharsets.ISO_8859_1); Assert.assertEquals(result, CHUNKED_RESULT); final Header[] footers = in.getFooters(); Assert.assertNotNull(footers); Assert.assertEquals(2, footers.length); Assert.assertEquals("Footer1", footers[0].getName()); Assert.assertEquals("abcde", footers[0].getValue()); Assert.assertEquals("Footer2", footers[1].getName()); Assert.assertEquals("fghij", footers[1].getValue()); }
protected InputStream createContentInputStream( final long len, final SessionInputBuffer buffer, final InputStream inputStream) { if (len > 0) { return new ContentLengthInputStream(buffer, inputStream, len); } else if (len == 0) { return EmptyInputStream.INSTANCE; } else if (len == ContentLengthStrategy.CHUNKED) { return new ChunkedInputStream(buffer, inputStream, this.h1Config); } else { return new IdentityInputStream(buffer, inputStream); } }
nextChunk(); if (this.eof) { return -1;
@Test(expected=MalformedChunkCodingException.class) public void testCorruptChunkedInputStreamTruncatedCRLF() throws IOException { final String s = "5\r\n01234"; final SessionInputBuffer inBuffer = new SessionInputBufferImpl(16); final ByteArrayInputStream inputStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.ISO_8859_1)); final ChunkedInputStream in = new ChunkedInputStream(inBuffer, inputStream); final byte[] tmp = new byte[5]; Assert.assertEquals(5, in.read(tmp)); in.read(); in.close(); }
/** * Read some bytes from the stream. * @param b The byte array that will hold the contents from the stream. * @return The number of bytes returned or -1 if the end of stream has been * reached. * @throws IOException in case of an I/O error */ @Override public int read (final byte[] b) throws IOException { return read(b, 0, b.length); }
/** * Read the next chunk. * @throws IOException in case of an I/O error */ private void nextChunk() throws IOException { if (state == State.CHUNK_INVALID) { throw new MalformedChunkCodingException("Corrupt data stream"); } try { chunkSize = getChunkSize(); if (chunkSize < 0L) { throw new MalformedChunkCodingException("Negative chunk size"); } state = State.CHUNK_DATA; pos = 0L; if (chunkSize == 0L) { eof = true; parseTrailerHeaders(); } } catch (final MalformedChunkCodingException ex) { state = State.CHUNK_INVALID; throw ex; } }
nextChunk(); if (eof) { return -1;
@Test(expected=MalformedChunkCodingException.class) public void testCorruptChunkedInputStreamMissingLF() throws IOException { final String s = "5\r01234\r\n5\r\n56789\r\n0\r\n"; final SessionInputBuffer inBuffer = new SessionInputBufferImpl(16); final ByteArrayInputStream inputStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.ISO_8859_1)); final ChunkedInputStream in = new ChunkedInputStream(inBuffer, inputStream); in.read(); in.close(); }
/** * Upon close, this reads the remainder of the chunked message, * leaving the underlying socket at a position to start reading the * next response without scanning. * @throws IOException in case of an I/O error */ @Override public void close() throws IOException { if (!closed) { try { if (!eof && state != State.CHUNK_INVALID) { // read and discard the remainder of the message final byte[] buff = new byte[BUFFER_SIZE]; while (read(buff) >= 0) { } } } finally { eof = true; closed = true; } } }
nextChunk(); if (eof) { return -1;
@Test(expected = MalformedChunkCodingException.class) public void testCorruptChunkedInputStreamNegativeSize() throws IOException { final String s = "-5\r\n01234\r\n5\r\n56789\r\n0\r\n"; final SessionInputBuffer inBuffer = new SessionInputBufferImpl(16); final ByteArrayInputStream inputStream = new ByteArrayInputStream(s.getBytes(StandardCharsets.ISO_8859_1)); final ChunkedInputStream in = new ChunkedInputStream(inBuffer, inputStream); in.read(); in.close(); }