diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java index aeba1953818..9b6c83b1fb0 100644 --- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java +++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpGenerator.java @@ -157,6 +157,12 @@ public class HttpGenerator return _endOfContent==EndOfContent.CHUNKED_CONTENT; } + /* ------------------------------------------------------------ */ + public boolean isNoContent() + { + return _noContent; + } + /* ------------------------------------------------------------ */ public void setPersistent(boolean persistent) { diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerTest.java index 90100154a3e..03992957e46 100644 --- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerTest.java +++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorServerTest.java @@ -72,7 +72,40 @@ public class HttpGeneratorServerTest assertThat(response, containsString("Content-Length: 10")); assertThat(response, containsString("\r\n0123456789")); } + + @Test + public void test204() throws Exception + { + ByteBuffer header = BufferUtil.allocate(8096); + ByteBuffer content = BufferUtil.toBuffer("0123456789"); + HttpGenerator gen = new HttpGenerator(); + + ResponseInfo info = new ResponseInfo(HttpVersion.HTTP_1_1, new HttpFields(), 10, 204, "Foo", false); + info.getHttpFields().add("Content-Type", "test/data"); + info.getHttpFields().add("Last-Modified", DateGenerator.__01Jan1970); + + HttpGenerator.Result result = gen.generateResponse(info, header, null, content, true); + + assertEquals(gen.isNoContent(), true); + assertEquals(HttpGenerator.Result.FLUSH, result); + assertEquals(HttpGenerator.State.COMPLETING, gen.getState()); + String responseheaders = BufferUtil.toString(header); + BufferUtil.clear(header); + + result = gen.generateResponse(null, null, null, content, false); + assertEquals(HttpGenerator.Result.DONE, result); + assertEquals(HttpGenerator.State.END, gen.getState()); + + assertThat(responseheaders, containsString("HTTP/1.1 204 Foo")); + assertThat(responseheaders, containsString("Last-Modified: Thu, 01 Jan 1970 00:00:00 GMT")); + assertThat(responseheaders, not(containsString("Content-Length: 10"))); + + //Note: the HttpConnection.process() method is responsible for actually + //excluding the content from the response based on generator.isNoContent()==true + } + + @Test public void testComplexChars() throws Exception { diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java index 5be5c31e3ee..bc89093eee0 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java @@ -537,8 +537,8 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http } case FLUSH: { - // Don't write the chunk or the content if this is a HEAD response - if (_channel.getRequest().isHead()) + // Don't write the chunk or the content if this is a HEAD response, or any other type of response that should have no content + if (_channel.getRequest().isHead() || _generator.isNoContent()) { BufferUtil.clear(chunk); BufferUtil.clear(_content); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index eb38f250bbc..938937f76ae 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -388,7 +388,7 @@ public class Request implements HttpServletRequest public AsyncContext getAsyncContext() { HttpChannelState state = getHttpChannelState(); - if (_async==null || state.isInitial() && !state.isAsync()) + if (_async==null || !state.isAsyncStarted()) throw new IllegalStateException(state.getStatusString()); return _async; diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncServletTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncServletTest.java index 5a50e834b2b..af7e06add14 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncServletTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncServletTest.java @@ -583,6 +583,17 @@ public class AsyncServletTest @Override public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { + // this should always fail at this point + try + { + request.getAsyncContext(); + throw new IllegalStateException(); + } + catch(IllegalStateException e) + { + // ignored + } + // System.err.println(request.getDispatcherType()+" "+request.getRequestURI()); response.addHeader("history",request.getDispatcherType()+" "+request.getRequestURI()); if (request instanceof ServletRequestWrapper || response instanceof ServletResponseWrapper) diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java index 017b9f1cf66..ff790ade10a 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java @@ -35,6 +35,8 @@ import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -68,7 +70,7 @@ import org.eclipse.jetty.util.log.Logger; * minutes *