diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java index a918541e041..86665bbbaf6 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java @@ -155,59 +155,54 @@ public class HttpOutput extends ServletOutputStream @Override public void write(byte[] b, int off, int len) throws IOException - { + { if (isClosed()) throw new EOFException("Closed"); - // Do we have an aggregate buffer ? - if (_aggregate == null) - { - // NO - should we have an aggregate buffer? yes if this write will easily fit in it - int size = getBufferSize(); - if (len<=size/2) - { - _aggregate = _channel.getByteBufferPool().acquire(size, false); - BufferUtil.append(_aggregate, b, off, len); - _written += len; - closeIfAllContentWritten(); - return; - } - } - else + _written+=len; + boolean complete=_channel.getResponse().isAllContentWritten(_written); + int capacity = getBufferSize(); + + // Should we aggregate? + if (!complete && len<=capacity/4) { + if (_aggregate == null) + _aggregate = _channel.getByteBufferPool().acquire(capacity, false); + // YES - fill the aggregate with content from the buffer int filled = BufferUtil.fill(_aggregate, b, off, len); - _written += filled; - - // if closed or there is no content left over and we are not full, then we are done - if (closeIfAllContentWritten() || filled==len && !BufferUtil.isFull(_aggregate)) + + // return if we are not complete, not full and filled all the content + if (!complete && filled==len && !BufferUtil.isFull(_aggregate)) return; - + + // adjust offset/length off+=filled; len-=filled; } - - // flush the aggregate + + // flush any content from the aggregate if (BufferUtil.hasContent(_aggregate)) { - _channel.write(_aggregate, false); - + _channel.write(_aggregate, complete && len==0); + // should we fill aggregate again from the buffer? - if (len<_aggregate.capacity()/2) + if (len>0 && !complete && len<=_aggregate.capacity()/4) { BufferUtil.append(_aggregate, b, off, len); - _written += len; - closeIfAllContentWritten(); return; } } - + // write any remaining content in the buffer directly - _written += len; - boolean complete=_channel.getResponse().isAllContentWritten(_written); - _channel.write(ByteBuffer.wrap(b, off, len), complete); + if (len>0) + _channel.write(ByteBuffer.wrap(b, off, len), complete); + if (complete) + { + closed(); _channel.getResponse().closeOutput(); + } } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToCommitTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToCommitTest.java index c567873b91b..cfc255f92ed 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToCommitTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpManyWaysToCommitTest.java @@ -327,7 +327,7 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest SimpleHttpResponse response = executeRequest(); assertThat("response code is 200", response.getCode(), is("200")); - assertResponseBody(response, "foobar"); + assertResponseBody(response, "foobarfoobar"); if (!"HTTP/1.0".equals(httpVersion)) assertHeader(response, "transfer-encoding", "chunked"); } @@ -341,7 +341,7 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest SimpleHttpResponse response = executeRequest(); assertThat("response code is 200", response.getCode(), is("200")); - assertResponseBody(response, "foobar"); + assertResponseBody(response, "foobarfoobar"); if (!"HTTP/1.0".equals(httpVersion)) assertHeader(response, "transfer-encoding", "chunked"); } @@ -372,7 +372,7 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); - response.setBufferSize(3); + response.setBufferSize(4); response.getWriter().write("foobar"); super.handle(target, baseRequest, request, response); } @@ -389,9 +389,9 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); - response.setBufferSize(3); - response.getWriter().write("f"); - response.getWriter().write("oobar"); + response.setBufferSize(8); + response.getWriter().write("fo"); + response.getWriter().write("obarfoobar"); super.handle(target, baseRequest, request, response); } } @@ -407,7 +407,10 @@ public class HttpManyWaysToCommitTest extends AbstractHttpTest public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { baseRequest.setHandled(true); - response.setBufferSize(5); + response.setBufferSize(8); + response.getWriter().write("fo"); + response.getWriter().write("ob"); + response.getWriter().write("ar"); response.getWriter().write("fo"); response.getWriter().write("ob"); response.getWriter().write("ar");