diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java index 35f764da383..c007ab71c60 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceService.java @@ -578,7 +578,7 @@ public class ResourceService { //Get jetty's Response impl String mdlm = content.getLastModifiedValue(); - if (mdlm != null && ifms.equals(mdlm)) + if (ifms.equals(mdlm)) { sendStatus(response, HttpServletResponse.SC_NOT_MODIFIED, content::getETagValue); return false; @@ -676,17 +676,17 @@ public class ResourceService writeContent(content, out, 0, content_length); } // else if we can't do a bypass write because of wrapping - else if (written || !(out instanceof HttpOutput)) + else if (written) { // write normally - putHeaders(response, content, written ? -1 : 0); + putHeaders(response, content, Response.NO_CONTENT_LENGTH); writeContent(content, out, 0, content_length); } // else do a bypass write else { // write the headers - putHeaders(response, content, 0); + putHeaders(response, content, Response.USE_KNOWN_CONTENT_LENGTH); // write the content asynchronously if supported if (request.isAsyncSupported() && content.getContentLengthValue() > response.getBufferSize()) @@ -735,7 +735,7 @@ public class ResourceService // if there are no satisfiable ranges, send 416 response if (ranges == null || ranges.size() == 0) { - putHeaders(response, content, 0); + putHeaders(response, content, Response.USE_KNOWN_CONTENT_LENGTH); response.setHeader(HttpHeader.CONTENT_RANGE.asString(), InclusiveByteRange.to416HeaderRangeString(content_length)); sendStatus(response, HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE, null); @@ -762,8 +762,8 @@ public class ResourceService // 216 response which does not require an overall // content-length header // - putHeaders(response, content, -1); - String mimetype = (content == null ? null : content.getContentTypeValue()); + putHeaders(response, content, Response.NO_CONTENT_LENGTH); + String mimetype = content.getContentTypeValue(); if (mimetype == null) LOG.warn("Unknown mimetype for {}", request.getRequestURI()); response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java index f46126a1a8b..4a3e65bee7d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java @@ -70,6 +70,8 @@ public class Response implements HttpServletResponse { private static final int __MIN_BUFFER_SIZE = 1; private static final HttpField __EXPIRES_01JAN1970 = new PreEncodedHttpField(HttpHeader.EXPIRES, DateGenerator.__01Jan1970); + public static final int NO_CONTENT_LENGTH = -1; + public static final int USE_KNOWN_CONTENT_LENGTH = -2; public enum OutputType { @@ -1339,12 +1341,12 @@ public class Response implements HttpServletResponse if (lm != null) _fields.put(lm); - if (contentLength == 0) + if (contentLength == USE_KNOWN_CONTENT_LENGTH) { _fields.put(content.getContentLength()); _contentLength = content.getContentLengthValue(); } - else if (contentLength > 0) + else if (contentLength > NO_CONTENT_LENGTH) { _fields.putLongField(HttpHeader.CONTENT_LENGTH, contentLength); _contentLength = contentLength; @@ -1387,9 +1389,9 @@ public class Response implements HttpServletResponse if (lml >= 0) response.setDateHeader(HttpHeader.LAST_MODIFIED.asString(), lml); - if (contentLength == 0) + if (contentLength == USE_KNOWN_CONTENT_LENGTH) contentLength = content.getContentLengthValue(); - if (contentLength >= 0) + if (contentLength > NO_CONTENT_LENGTH) { if (contentLength < Integer.MAX_VALUE) response.setContentLength((int)contentLength); diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java index 2be9f6c928d..e704b6f0646 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java @@ -464,16 +464,24 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory, Welc } @Override - protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException + protected void doHead(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { - resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); + doGet(request, response); } @Override - protected void doOptions(HttpServletRequest req, HttpServletResponse resp) + protected void doTrace(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - resp.setHeader("Allow", "GET,HEAD,POST,OPTIONS"); + response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); + } + + @Override + protected void doOptions(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + response.setHeader("Allow", "GET,HEAD,POST,OPTIONS"); } @Override diff --git a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/HugeResourceTest.java b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/HugeResourceTest.java index 7bb613c79c5..f0ad5ab295c 100644 --- a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/HugeResourceTest.java +++ b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/HugeResourceTest.java @@ -238,6 +238,31 @@ public class HugeResourceTest } } + @ParameterizedTest + @MethodSource("staticFiles") + public void testHead(String filename, long expectedSize) throws Exception + { + URI destUri = server.getURI().resolve("/" + filename); + InputStreamResponseListener responseListener = new InputStreamResponseListener(); + + Request request = client.newRequest(destUri) + .method(HttpMethod.HEAD); + request.send(responseListener); + Response response = responseListener.get(5, TimeUnit.SECONDS); + + try (InputStream in = responseListener.getInputStream()) + { + assertThat(in.read(), is(-1)); + } + + assertThat("HTTP Response Code", response.getStatus(), is(200)); + // dumpResponse(response); + + String contentLength = response.getHeaders().get(HttpHeader.CONTENT_LENGTH); + long contentLengthLong = Long.parseLong(contentLength); + assertThat("Http Response Header: \"Content-Length: " + contentLength + "\"", contentLengthLong, is(expectedSize)); + } + @ParameterizedTest @MethodSource("staticFiles") public void testUpload(String filename, long expectedSize) throws Exception