From f0a99306939dee0e013575a3055875c9978d3d5f Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Mon, 24 Dec 2012 13:52:28 +1100 Subject: [PATCH] 397112 Requests with byte-range throws NPE if requested file has no mimetype (eg no file extension) --- .../eclipse/jetty/servlet/DefaultServlet.java | 6 +- .../jetty/servlet/DefaultServletTest.java | 56 +++++++++++++++++++ .../jetty/util/MultiPartOutputStream.java | 6 +- 3 files changed, 64 insertions(+), 4 deletions(-) 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 11fac730bc3..7d87278e553 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 @@ -971,7 +971,9 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory // content-length header // writeHeaders(response,content,-1); - String mimetype=content.getContentType().toString(); + String mimetype=(content.getContentType()==null?null:content.getContentType().toString()); + if (mimetype==null) + LOG.warn("Unknown mimetype for "+request.getRequestURI()); MultiPartOutputStream multi = new MultiPartOutputStream(out); response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); @@ -998,7 +1000,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory length+= ((i>0)?2:0)+ 2+multi.getBoundary().length()+2+ - HttpHeaders.CONTENT_TYPE.length()+2+mimetype.length()+2+ + (mimetype==null?0:HttpHeaders.CONTENT_TYPE.length()+2+mimetype.length())+2+ HttpHeaders.CONTENT_RANGE.length()+2+header[i].length()+2+ 2+ (ibr.getLast(content_length)-ibr.getFirst(content_length))+1; diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java index 31eda5958e9..0a837f58a9f 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java @@ -543,8 +543,64 @@ public class DefaultServletTest assertResponseContains("Content-Range: bytes 70-79/80", response); assertResponseContains("Content-Length: " + body.length(), response); assertTrue(body.endsWith(boundary + "--\r\n")); + + //test a range request with a file with no suffix, therefore no mimetype + File nofilesuffix = new File(resBase, "nofilesuffix"); + createFile(nofilesuffix, "01234567890123456789012345678901234567890123456789012345678901234567890123456789"); + response = connector.getResponses( + "GET /context/nofilesuffix HTTP/1.1\r\n" + + "Host: localhost\r\n" + + "\r\n"); + assertResponseContains("200 OK", response); + assertResponseContains("Accept-Ranges: bytes", response); + + response = connector.getResponses( + "GET /context/nofilesuffix HTTP/1.1\r\n" + + "Host: localhost\r\n" + + "Range: bytes=0-9\r\n" + + "\r\n"); + assertResponseContains("206 Partial", response); + assertResponseContains("Content-Length: 10", response); + assertTrue(!response.contains("Content-Type:")); + assertResponseContains("Content-Range: bytes 0-9/80", response); + + response = connector.getResponses( + "GET /context/nofilesuffix HTTP/1.1\r\n" + + "Host: localhost\r\n" + + "Range: bytes=0-9,20-29,40-49\r\n" + + "\r\n"); + start = response.indexOf("--jetty"); + body = response.substring(start); + boundary = body.substring(0, body.indexOf("\r\n")); + assertResponseContains("206 Partial", response); + assertResponseContains("Content-Type: multipart/byteranges; boundary=", response); + assertResponseContains("Content-Range: bytes 0-9/80", response); + assertResponseContains("Content-Range: bytes 20-29/80", response); + assertResponseContains("Content-Length: " + body.length(), response); + assertTrue(body.endsWith(boundary + "--\r\n")); + + response = connector.getResponses( + "GET /context/nofilesuffix HTTP/1.1\r\n" + + "Host: localhost\r\n" + + "Range: bytes=0-9,20-29,40-49,60-60,70-79\r\n" + + "\r\n"); + start = response.indexOf("--jetty"); + body = response.substring(start); + boundary = body.substring(0, body.indexOf("\r\n")); + assertResponseContains("206 Partial", response); + assertResponseContains("Content-Type: multipart/byteranges; boundary=", response); + assertResponseContains("Content-Range: bytes 0-9/80", response); + assertResponseContains("Content-Range: bytes 20-29/80", response); + assertResponseContains("Content-Range: bytes 60-60/80", response); + assertResponseContains("Content-Range: bytes 70-79/80", response); + assertResponseContains("Content-Length: " + body.length(), response); + assertTrue(body.endsWith(boundary + "--\r\n")); + } + + + @Test public void testFiltered() throws Exception { diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartOutputStream.java b/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartOutputStream.java index 17f3c8f202e..c1fe9e6c352 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartOutputStream.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartOutputStream.java @@ -98,7 +98,8 @@ public class MultiPartOutputStream extends FilterOutputStream out.write(__DASHDASH); out.write(boundaryBytes); out.write(__CRLF); - out.write(("Content-Type: "+contentType).getBytes(StringUtil.__ISO_8859_1)); + if (contentType != null) + out.write(("Content-Type: "+contentType).getBytes(StringUtil.__ISO_8859_1)); out.write(__CRLF); out.write(__CRLF); } @@ -115,7 +116,8 @@ public class MultiPartOutputStream extends FilterOutputStream out.write(__DASHDASH); out.write(boundaryBytes); out.write(__CRLF); - out.write(("Content-Type: "+contentType).getBytes(StringUtil.__ISO_8859_1)); + if (contentType != null) + out.write(("Content-Type: "+contentType).getBytes(StringUtil.__ISO_8859_1)); out.write(__CRLF); for (int i=0;headers!=null && i