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 45eacba982f..1b676da6534 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 @@ -680,20 +680,39 @@ public class HttpOutput extends ServletOutputStream implements Runnable { Throwable th=_onError; _onError=null; - _writeListener.onError(th); + _writeListener.onError(new IOException(th)); close(); } - if (_state.get()==OutputState.READY) + switch(_state.get()) { - try - { - _writeListener.onWritePossible(); - } - catch (Throwable e) - { - _writeListener.onError(e); - close(); - } + case READY: + try + { + _writeListener.onWritePossible(); + } + catch (Throwable e) + { + _writeListener.onError(e); + close(); + } + break; + + case CLOSED: + try + { + // even though a write is not possible, because a close has + // occurred, we need to call onWritePossible to tell async + // producer that the last write completed. + _writeListener.onWritePossible(); + } + catch (Throwable e) + { + _writeListener.onError(e); + } + break; + + default: + } } @@ -722,7 +741,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable break; case CLOSED: - _onError=new EofException("Closed"); + _channel.getState().onWritePossible(); break; default: diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpOutputTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpOutputTest.java index ead2774b8fa..4102b474582 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpOutputTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpOutputTest.java @@ -348,7 +348,7 @@ public class HttpOutputTest assertThat(response,containsString("Content-Length")); assertThat(response,containsString("400\tThis is a big file")); } - + @Test public void testWriteLargeKnown() throws Exception { @@ -546,6 +546,22 @@ public class HttpOutputTest assertThat(response,Matchers.not(containsString("Content-Length"))); assertThat(response,containsString("400\tThis is a big file")); } + + @Test + public void testAsyncWriteSimpleKnown() throws Exception + { + final Resource big = Resource.newClassPathResource("simple/simple.txt"); + + _handler._async=true; + _handler._writeLengthIfKnown=true; + _handler._content=BufferUtil.toBuffer(big,false); + _handler._arrayBuffer=new byte[4000]; + + String response=_connector.getResponses("GET / HTTP/1.0\nHost: localhost:80\n\n"); + assertThat(response,containsString("HTTP/1.1 200 OK")); + assertThat(response,containsString("Content-Length: 11")); + assertThat(response,containsString("simple text")); + } static class ContentHandler extends AbstractHandler { @@ -664,7 +680,6 @@ public class HttpOutputTest BufferUtil.flipToFlush(_byteBuffer,0); out.write(_byteBuffer); } - Assert.assertFalse(out.isReady()); } @Override