From 144a460407c493ef5b0155b136819850f848c41b Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Mon, 9 Jun 2014 18:35:49 +0200 Subject: [PATCH] 436894 GzipFilter code cleanup --- .../org/eclipse/jetty/http/mime.properties | 1 + .../eclipse/jetty/servlet/DefaultServlet.java | 42 +- .../jetty/servlets/AsyncGzipFilter.java | 19 +- .../eclipse/jetty/servlets/GzipFilter.java | 19 +- .../jetty/servlets/gzip/GzipHttpOutput.java | 11 + .../jetty/servlets/GzipFilterDefaultTest.java | 38 + .../jetty/servlets/gzip/GzipTester.java | 28 +- jetty-servlets/src/test/resources/test.svg | 2101 +++++++++++++++++ .../src/test/resources/test.svg.sha1 | 1 + jetty-servlets/src/test/resources/test.svgz | Bin 0 -> 6916 bytes .../src/test/resources/test.svgz.sha1 | 1 + 11 files changed, 2248 insertions(+), 13 deletions(-) create mode 100644 jetty-servlets/src/test/resources/test.svg create mode 100644 jetty-servlets/src/test/resources/test.svg.sha1 create mode 100644 jetty-servlets/src/test/resources/test.svgz create mode 100644 jetty-servlets/src/test/resources/test.svgz.sha1 diff --git a/jetty-http/src/main/resources/org/eclipse/jetty/http/mime.properties b/jetty-http/src/main/resources/org/eclipse/jetty/http/mime.properties index b2709897ae5..654454c7a14 100644 --- a/jetty-http/src/main/resources/org/eclipse/jetty/http/mime.properties +++ b/jetty-http/src/main/resources/org/eclipse/jetty/http/mime.properties @@ -141,6 +141,7 @@ src=application/x-wais-source sv4cpio=application/x-sv4cpio sv4crc=application/x-sv4crc svg=image/svg+xml +svgz=image/svg+xml swf=application/x-shockwave-flash t=application/x-troff tar=application/x-tar 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 c3787395d38..30741657a15 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 @@ -25,8 +25,12 @@ import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.Enumeration; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.StringTokenizer; import javax.servlet.AsyncContext; import javax.servlet.RequestDispatcher; @@ -125,6 +129,9 @@ import org.eclipse.jetty.util.resource.ResourceFactory; * * cacheControl If set, all static content will have this value set as the cache-control * header. + * + * otherGzipFileExtensions + * Other file extensions that signify that a file is gzip compressed. Eg ".svgz" * * * @@ -164,6 +171,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory private String _relativeResourceBase; private ServletHandler _servletHandler; private ServletHolder _defaultHolder; + private List _gzipEquivalentFileExtensions; /* ------------------------------------------------------------ */ @Override @@ -273,6 +281,24 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory LOG.warn(Log.EXCEPTION,e); throw new UnavailableException(e.toString()); } + + _gzipEquivalentFileExtensions = new ArrayList(); + String otherGzipExtensions = getInitParameter("otherGzipFileExtensions"); + if (otherGzipExtensions != null) + { + //comma separated list + StringTokenizer tok = new StringTokenizer(otherGzipExtensions,",",false); + while (tok.hasMoreTokens()) + { + String s = tok.nextToken().trim(); + _gzipEquivalentFileExtensions.add((s.charAt(0)=='.'?s:"."+s)); + } + } + else + { + //.svgz files are gzipped svg files and must be served with Content-Encoding:gzip + _gzipEquivalentFileExtensions.add(".svgz"); + } _servletHandler= _contextHandler.getChildHandlerByClass(ServletHandler.class); for (ServletHolder h :_servletHandler.getServlets()) @@ -496,7 +522,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory if (included.booleanValue() || passConditionalHeaders(request,response, resource,content)) { - if (gzip) + if (gzip || isGzippedContent(pathInContext)) { response.setHeader(HttpHeader.CONTENT_ENCODING.asString(),"gzip"); String mt=_servletContext.getMimeType(pathInContext); @@ -585,6 +611,20 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory } + /** + * @param resource + * @return + */ + protected boolean isGzippedContent(String path) + { + if (path == null) return false; + + for (String suffix:_gzipEquivalentFileExtensions) + if (path.endsWith(suffix)) + return true; + return false; + } + /* ------------------------------------------------------------ */ private boolean hasDefinedRange(Enumeration reqRanges) { diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/AsyncGzipFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/AsyncGzipFilter.java index c9523ae2e89..6eb7c152aa3 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/AsyncGzipFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/AsyncGzipFilter.java @@ -209,14 +209,16 @@ public class AsyncGzipFilter extends UserAgentFilter implements GzipFactory { for (String type:MimeTypes.getKnownMimeTypes()) { + if (type.equals("image/svg+xml")) //always compressable (unless .svgz file) + continue; if (type.startsWith("image/")|| type.startsWith("audio/")|| type.startsWith("video/")) _mimeTypes.add(type); - _mimeTypes.add("application/compress"); - _mimeTypes.add("application/zip"); - _mimeTypes.add("application/gzip"); } + _mimeTypes.add("application/compress"); + _mimeTypes.add("application/zip"); + _mimeTypes.add("application/gzip"); } else { @@ -317,11 +319,11 @@ public class AsyncGzipFilter extends UserAgentFilter implements GzipFactory } // Exclude non compressible mime-types known from URI extension. - no Vary because no matter what client, this URI is always excluded - if (_mimeTypes.size()>0) + if (_mimeTypes.size()>0 && _excludeMimeTypes) { String mimeType = _context.getMimeType(request.getRequestURI()); - if (mimeType!=null && _mimeTypes.contains(mimeType)==_excludeMimeTypes) + if (mimeType!=null && _mimeTypes.contains(mimeType)) { LOG.debug("{} excluded by path suffix {}",this,request); // handle normally without setting vary header @@ -330,6 +332,13 @@ public class AsyncGzipFilter extends UserAgentFilter implements GzipFactory } } + //If the Content-Encoding is already set, then we won't compress + if (response.getHeader("Content-Encoding") != null) + { + super.doFilter(request,response,chain); + return; + } + if (_checkGzExists && request.getServletContext()!=null) { String path=request.getServletContext().getRealPath(URIUtil.addPaths(request.getServletPath(),request.getPathInfo())); diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java index e376349e703..69f2f62f119 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java @@ -208,14 +208,16 @@ public class GzipFilter extends UserAgentFilter { for (String type:MimeTypes.getKnownMimeTypes()) { + if (type.equals("image/svg+xml")) //always compressable (unless .svgz file) + continue; if (type.startsWith("image/")|| type.startsWith("audio/")|| type.startsWith("video/")) _mimeTypes.add(type); - _mimeTypes.add("application/compress"); - _mimeTypes.add("application/zip"); - _mimeTypes.add("application/gzip"); } + _mimeTypes.add("application/compress"); + _mimeTypes.add("application/zip"); + _mimeTypes.add("application/gzip"); } else { @@ -300,17 +302,24 @@ public class GzipFilter extends UserAgentFilter } // Exclude non compressible mime-types known from URI extension. - no Vary because no matter what client, this URI is always excluded - if (_mimeTypes.size()>0) + if (_mimeTypes.size()>0 && _excludeMimeTypes) { String mimeType = _context.getMimeType(request.getRequestURI()); - if (mimeType!=null && _mimeTypes.contains(mimeType)==_excludeMimeTypes) + if (mimeType!=null && _mimeTypes.contains(mimeType)) { // handle normally without setting vary header super.doFilter(request,response,chain); return; } } + + //If the Content-Encoding is already set, then we won't compress + if (response.getHeader("Content-Encoding") != null) + { + super.doFilter(request,response,chain); + return; + } if (_checkGzExists && request.getServletContext()!=null) { diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/GzipHttpOutput.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/GzipHttpOutput.java index 3151ab8e5a9..063a76c97f1 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/GzipHttpOutput.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/GzipHttpOutput.java @@ -151,6 +151,16 @@ public class GzipHttpOutput extends HttpOutput } } + // Has the Content-Encoding header already been site? + String ce=getHttpChannel().getResponse().getHeader("Content-Encoding"); + if (ce != null) + { + LOG.debug("{} exclude by content-encoding {}",this,ce); + noCompression(); + super.write(content,complete,callback); + return; + } + // Are we the thread that commits? if (_state.compareAndSet(GZState.MIGHT_COMPRESS,GZState.COMMITTING)) { @@ -188,6 +198,7 @@ public class GzipHttpOutput extends HttpOutput gzip(content,complete,callback); } + // TODO else ? } public void noCompression() diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java index 81aa29ec97a..bdcac4218d1 100644 --- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java +++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java @@ -273,6 +273,24 @@ public class GzipFilterDefaultTest } } + @Test + public void testGzippedIfSVG() throws Exception + { + GzipTester tester = new GzipTester(testingdir, compressionType); + tester.setGzipFilterClass(testFilter); + tester.copyTestServerFile("test.svg"); + FilterHolder holder = tester.setContentServlet(org.eclipse.jetty.servlet.DefaultServlet.class); + try + { + tester.start(); + HttpTester.Response http = tester.assertIsResponseGzipCompressed("GET","test.svg",System.currentTimeMillis()-4000); + Assert.assertEquals("Accept-Encoding",http.get("Vary")); + } + finally + { + tester.stop(); + } + } @Test public void testNotGzipedIfNotModified() throws Exception @@ -553,4 +571,24 @@ public class GzipFilterDefaultTest tester.stop(); } } + + + @Test + public void testIsNotGzipCompressedSVGZ() throws Exception + { + GzipTester tester = new GzipTester(testingdir,compressionType); + tester.setGzipFilterClass(testFilter); + + FilterHolder holder = tester.setContentServlet(DefaultServlet.class); + tester.copyTestServerFile("test.svgz"); + try + { + tester.start(); + tester.assertIsResponseNotGzipFiltered("test.svgz", "test.svgz.sha1", "image/svg+xml", "gzip"); + } + finally + { + tester.stop(); + } + } } diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java index f6bfbb8c1cb..657c6dfc85b 100644 --- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java +++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java @@ -282,6 +282,27 @@ public class GzipTester * @param expectedContentType */ public void assertIsResponseNotGzipFiltered(String requestedFilename, String testResourceSha1Sum, String expectedContentType) throws Exception + { + assertIsResponseNotGzipFiltered(requestedFilename, testResourceSha1Sum, expectedContentType,null); + } + + /** + * Makes sure that the response contains an unfiltered file contents. + *

+ * This is used to test exclusions and passthroughs in the GzipFilter. + *

+ * An example is to test that it is possible to configure GzipFilter to not recompress content that shouldn't be + * compressed by the GzipFilter. + * + * @param requestedFilename + * the filename used to on the GET request,. + * @param testResourceSha1Sum + * the sha1sum file that contains the SHA1SUM checksum that will be used to verify that the response + * contents are what is intended. + * @param expectedContentType + * @param expectedContentEncoding can be non-null in some circumstances, eg when dealing with pre-gzipped .svgz files + */ + public void assertIsResponseNotGzipFiltered(String requestedFilename, String testResourceSha1Sum, String expectedContentType, String expectedContentEncoding) throws Exception { //System.err.printf("[GzipTester] requesting /context/%s%n",requestedFilename); HttpTester.Request request = HttpTester.newRequest(); @@ -304,7 +325,10 @@ public class GzipTester String prefix = requestedFilename + " / Response"; Assert.assertThat(prefix + ".status",response.getStatus(),is(HttpServletResponse.SC_OK)); Assert.assertThat(prefix + ".header[Content-Length]",response.get("Content-Length"),notNullValue()); - Assert.assertThat(prefix + ".header[Content-Encoding] (should not be recompressed by GzipFilter)",response.get("Content-Encoding"),nullValue()); + Assert.assertThat(prefix + ".header[Content-Encoding] (should not be recompressed by GzipFilter)",response.get("Content-Encoding"), + expectedContentEncoding == null? nullValue() : notNullValue()); + if (expectedContentEncoding != null) + Assert.assertThat(prefix + ".header[Content-Encoding]",response.get("Content-Encoding"),is(expectedContentEncoding)); Assert.assertThat(prefix + ".header[Content-Type] (should have a Content-Type associated with it)",response.get("Content-Type"),notNullValue()); Assert.assertThat(prefix + ".header[Content-Type]",response.get("Content-Type"),is(expectedContentType)); @@ -339,7 +363,7 @@ public class GzipTester { String name = names.nextElement(); String value = message.get(name); - //System.out.printf(" [%s] = %s%n",name,value); + //System.out.printf(" [%s] = %s%n",name,value); } } diff --git a/jetty-servlets/src/test/resources/test.svg b/jetty-servlets/src/test/resources/test.svg new file mode 100644 index 00000000000..08fbae33514 --- /dev/null +++ b/jetty-servlets/src/test/resources/test.svg @@ -0,0 +1,2101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jetty-servlets/src/test/resources/test.svg.sha1 b/jetty-servlets/src/test/resources/test.svg.sha1 new file mode 100644 index 00000000000..3b170f0b098 --- /dev/null +++ b/jetty-servlets/src/test/resources/test.svg.sha1 @@ -0,0 +1 @@ +1ccb7a0b85585d0e9bdc3863ad093d4e53a9ea68 test.svg diff --git a/jetty-servlets/src/test/resources/test.svgz b/jetty-servlets/src/test/resources/test.svgz new file mode 100644 index 0000000000000000000000000000000000000000..c4d595ffd0a9ec7e5a8d7d86c51b3121ac1cd921 GIT binary patch literal 6916 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 K{07oO76AZ9pm`(! literal 0 HcmV?d00001 diff --git a/jetty-servlets/src/test/resources/test.svgz.sha1 b/jetty-servlets/src/test/resources/test.svgz.sha1 new file mode 100644 index 00000000000..e8ec3aa6650 --- /dev/null +++ b/jetty-servlets/src/test/resources/test.svgz.sha1 @@ -0,0 +1 @@ +62df7c3ac6ee6e4462b6abf9ef15b4e916ecf68f test.svgz