You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2019/03/28 11:24:10 UTC

[httpcomponents-core] branch PR-114 created (now 7068d0c)

This is an automated email from the ASF dual-hosted git repository.

olegk pushed a change to branch PR-114
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git.


      at 7068d0c  HTTPCORE-573 FileContentDecoder don't always enforce the maximum number of bytes to transfer

This branch includes the following new commits:

     new 7068d0c  HTTPCORE-573 FileContentDecoder don't always enforce the maximum number of bytes to transfer

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[httpcomponents-core] 01/01: HTTPCORE-573 FileContentDecoder don't always enforce the maximum number of bytes to transfer

Posted by ol...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

olegk pushed a commit to branch PR-114
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git

commit 7068d0c3750cd54a136df7fadb1dbbac9cd3e201
Author: Julien Coloos <ju...@gmail.com>
AuthorDate: Tue Mar 26 17:45:32 2019 +0100

    HTTPCORE-573 FileContentDecoder don't always enforce the maximum number of bytes to transfer
    
    Limit the number of bytes read from the internal buffer when
    transferring, so that the maximum requested ('count') is respected.
---
 .../hc/core5/http/impl/nio/IdentityDecoder.java    |  3 +-
 .../http/impl/nio/LengthDelimitedDecoder.java      |  2 +-
 .../core5/http/impl/nio/TestIdentityDecoder.java   | 67 ++++++++++++++++++++++
 .../http/impl/nio/TestLengthDelimitedDecoder.java  | 67 ++++++++++++++++++++++
 4 files changed, 137 insertions(+), 2 deletions(-)

diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/IdentityDecoder.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/IdentityDecoder.java
index 08f03a3..06935ac 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/IdentityDecoder.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/IdentityDecoder.java
@@ -92,8 +92,9 @@ public class IdentityDecoder extends AbstractContentDecoder implements FileConte
 
         long bytesRead;
         if (this.buffer.hasData()) {
+            final int maxLen = this.buffer.length();
             dst.position(position);
-            bytesRead = this.buffer.read(dst);
+            bytesRead = this.buffer.read(dst, count < maxLen ? (int)count : maxLen);
         } else {
             if (this.channel.isOpen()) {
                 if (position > dst.size()) {
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/LengthDelimitedDecoder.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/LengthDelimitedDecoder.java
index 1a00718..46849b8 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/LengthDelimitedDecoder.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/nio/LengthDelimitedDecoder.java
@@ -119,7 +119,7 @@ public class LengthDelimitedDecoder extends AbstractContentDecoder implements Fi
         if (this.buffer.hasData()) {
             final int maxLen = Math.min(chunk, this.buffer.length());
             dst.position(position);
-            bytesRead = this.buffer.read(dst, maxLen);
+            bytesRead = this.buffer.read(dst, count < maxLen ? (int)count : maxLen);
         } else {
             if (this.channel.isOpen()) {
                 if (position > dst.size()) {
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestIdentityDecoder.java b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestIdentityDecoder.java
index e077211..dd8af8e 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestIdentityDecoder.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestIdentityDecoder.java
@@ -255,6 +255,73 @@ public class TestIdentityDecoder {
     }
 
     @Test
+    public void testDecodingFileWithLimit() throws Exception {
+        final ReadableByteChannel channel = new ReadableByteChannelMock(
+                new String[] {"stuff; more stuff; ", "a lot more stuff!"}, StandardCharsets.US_ASCII);
+
+        final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
+        final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
+        final IdentityDecoder decoder = new IdentityDecoder(channel, inbuf, metrics);
+
+        final int i = inbuf.fill(channel);
+        Assert.assertEquals(19, i);
+
+        createTempFile();
+        final RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
+        try {
+            final FileChannel fchannel = testfile.getChannel();
+            long pos = 0;
+
+            // transferred from buffer
+            long bytesRead = decoder.transfer(fchannel, pos, 1);
+            Assert.assertEquals(1, bytesRead);
+            Assert.assertFalse(decoder.isCompleted());
+            Assert.assertEquals(0, metrics.getBytesTransferred());
+            pos += bytesRead;
+
+            bytesRead = decoder.transfer(fchannel, pos, 2);
+            Assert.assertEquals(2, bytesRead);
+            Assert.assertFalse(decoder.isCompleted());
+            Assert.assertEquals(0, metrics.getBytesTransferred());
+            pos += bytesRead;
+
+            bytesRead = decoder.transfer(fchannel, pos, 17);
+            Assert.assertEquals(16, bytesRead);
+            Assert.assertFalse(decoder.isCompleted());
+            Assert.assertEquals(0, metrics.getBytesTransferred());
+            pos += bytesRead;
+
+            // transferred from channel
+            bytesRead = decoder.transfer(fchannel, pos, 1);
+            Assert.assertEquals(1, bytesRead);
+            Assert.assertFalse(decoder.isCompleted());
+            Assert.assertEquals(1, metrics.getBytesTransferred());
+            pos += bytesRead;
+
+            bytesRead = decoder.transfer(fchannel, pos, 2);
+            Assert.assertEquals(2, bytesRead);
+            Assert.assertFalse(decoder.isCompleted());
+            Assert.assertEquals(3, metrics.getBytesTransferred());
+            pos += bytesRead;
+
+            bytesRead = decoder.transfer(fchannel, pos, 15);
+            Assert.assertEquals(14, bytesRead);
+            Assert.assertFalse(decoder.isCompleted());
+            Assert.assertEquals(17, metrics.getBytesTransferred());
+            pos += bytesRead;
+
+            bytesRead = decoder.transfer(fchannel, pos, 1);
+            Assert.assertEquals(-1, bytesRead);
+            Assert.assertTrue(decoder.isCompleted());
+            Assert.assertEquals(17, metrics.getBytesTransferred());
+        } finally {
+            testfile.close();
+        }
+        Assert.assertEquals("stuff; more stuff; a lot more stuff!",
+                CodecTestUtils.readFromFile(this.tmpfile));
+    }
+
+    @Test
     public void testWriteBeyondFileSize() throws Exception {
         final ReadableByteChannel channel = new ReadableByteChannelMock(
                 new String[] {"a"}, StandardCharsets.US_ASCII);
diff --git a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestLengthDelimitedDecoder.java b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestLengthDelimitedDecoder.java
index 34b241c..3a0b96e 100644
--- a/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestLengthDelimitedDecoder.java
+++ b/httpcore5/src/test/java/org/apache/hc/core5/http/impl/nio/TestLengthDelimitedDecoder.java
@@ -363,6 +363,73 @@ public class TestLengthDelimitedDecoder {
     }
 
     @Test
+    public void testDecodingFileWithLimit() throws Exception {
+        final ReadableByteChannel channel = new ReadableByteChannelMock(
+                new String[] {"stuff; more stuff; ", "a lot more stuff!!!"}, StandardCharsets.US_ASCII);
+
+        final SessionInputBuffer inbuf = new SessionInputBufferImpl(1024, 256, 0, StandardCharsets.US_ASCII);
+        final BasicHttpTransportMetrics metrics = new BasicHttpTransportMetrics();
+        final LengthDelimitedDecoder decoder = new LengthDelimitedDecoder(channel, inbuf, metrics, 36);
+
+        final int i = inbuf.fill(channel);
+        Assert.assertEquals(19, i);
+
+        createTempFile();
+        final RandomAccessFile testfile = new RandomAccessFile(this.tmpfile, "rw");
+        try {
+            final FileChannel fchannel = testfile.getChannel();
+            long pos = 0;
+
+            // transferred from buffer
+            long bytesRead = decoder.transfer(fchannel, pos, 1);
+            Assert.assertEquals(1, bytesRead);
+            Assert.assertFalse(decoder.isCompleted());
+            Assert.assertEquals(0, metrics.getBytesTransferred());
+            pos += bytesRead;
+
+            bytesRead = decoder.transfer(fchannel, pos, 2);
+            Assert.assertEquals(2, bytesRead);
+            Assert.assertFalse(decoder.isCompleted());
+            Assert.assertEquals(0, metrics.getBytesTransferred());
+            pos += bytesRead;
+
+            bytesRead = decoder.transfer(fchannel, pos, 17);
+            Assert.assertEquals(16, bytesRead);
+            Assert.assertFalse(decoder.isCompleted());
+            Assert.assertEquals(0, metrics.getBytesTransferred());
+            pos += bytesRead;
+
+            // transferred from channel
+            bytesRead = decoder.transfer(fchannel, pos, 1);
+            Assert.assertEquals(1, bytesRead);
+            Assert.assertFalse(decoder.isCompleted());
+            Assert.assertEquals(1, metrics.getBytesTransferred());
+            pos += bytesRead;
+
+            bytesRead = decoder.transfer(fchannel, pos, 2);
+            Assert.assertEquals(2, bytesRead);
+            Assert.assertFalse(decoder.isCompleted());
+            Assert.assertEquals(3, metrics.getBytesTransferred());
+            pos += bytesRead;
+
+            bytesRead = decoder.transfer(fchannel, pos, 15);
+            Assert.assertEquals(14, bytesRead);
+            Assert.assertTrue(decoder.isCompleted());
+            Assert.assertEquals(17, metrics.getBytesTransferred());
+            pos += bytesRead;
+
+            bytesRead = decoder.transfer(fchannel, pos, 1);
+            Assert.assertEquals(-1, bytesRead);
+            Assert.assertTrue(decoder.isCompleted());
+            Assert.assertEquals(17, metrics.getBytesTransferred());
+        } finally {
+            testfile.close();
+        }
+        Assert.assertEquals("stuff; more stuff; a lot more stuff!",
+                CodecTestUtils.readFromFile(this.tmpfile));
+    }
+
+    @Test
     public void testWriteBeyondFileSize() throws Exception {
         final ReadableByteChannel channel = new ReadableByteChannelMock(
                 new String[] {"a"}, StandardCharsets.US_ASCII);