Author: markt Date: Thu Oct 10 21:24:59 2013 New Revision: 1531115 URL: http://svn.apache.org/r1531115 Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=54095 Add support to the Default Servlet for serving gzipped versions of static resources directly from disk as an alternative to Tomcat compressing them on each request. Patch by Philippe Marschall.
Added: tomcat/trunk/test/webapp/index.html.gz (with props) Modified: tomcat/trunk/conf/web.xml tomcat/trunk/java/org/apache/catalina/servlets/DefaultServlet.java tomcat/trunk/test/org/apache/catalina/servlets/TestDefaultServlet.java tomcat/trunk/webapps/docs/changelog.xml tomcat/trunk/webapps/docs/default-servlet.xml Modified: tomcat/trunk/conf/web.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/conf/web.xml?rev=1531115&r1=1531114&r2=1531115&view=diff ============================================================================== --- tomcat/trunk/conf/web.xml (original) +++ tomcat/trunk/conf/web.xml Thu Oct 10 21:24:59 2013 @@ -104,6 +104,10 @@ <param-name>listings</param-name> <param-value>false</param-value> </init-param> + <init-param> + <param-name>gzip</param-name> + <param-value>true</param-value> + </init-param> <load-on-startup>1</load-on-startup> </servlet> Modified: tomcat/trunk/java/org/apache/catalina/servlets/DefaultServlet.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/servlets/DefaultServlet.java?rev=1531115&r1=1531114&r2=1531115&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/servlets/DefaultServlet.java (original) +++ tomcat/trunk/java/org/apache/catalina/servlets/DefaultServlet.java Thu Oct 10 21:24:59 2013 @@ -32,6 +32,7 @@ import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; import java.util.ArrayList; +import java.util.Enumeration; import java.util.Iterator; import java.util.StringTokenizer; @@ -140,6 +141,12 @@ public class DefaultServlet /** + * Should be serve gzip versions of files. By default, it's set to true. + */ + protected boolean gzip = true; + + + /** * The output buffer size to use when serving resources. */ protected int output = 2048; @@ -277,6 +284,9 @@ public class DefaultServlet if (getServletConfig().getInitParameter("readonly") != null) readOnly = Boolean.parseBoolean(getServletConfig().getInitParameter("readonly")); + if (getServletConfig().getInitParameter("gzip") != null) + gzip = Boolean.parseBoolean(getServletConfig().getInitParameter("gzip")); + if (getServletConfig().getInitParameter("sendfileSize") != null) sendfileSize = Integer.parseInt(getServletConfig().getInitParameter("sendfileSize")) * 1024; @@ -754,6 +764,19 @@ public class DefaultServlet resource.setMimeType(contentType); } + // Serve a gzipped version of the file if present + if (gzip + && checkIfGzip(request) + && resource.isFile() + && !path.endsWith(".gz")) { + WebResource gzipResource = resources.getResource(path + ".gz"); + if (gzipResource.exists() && gzipResource.isFile()) { + gzipResource.setMimeType(contentType); + response.addHeader("Content-Encoding", "gzip"); + resource = gzipResource; + } + } + ArrayList<Range> ranges = null; long contentLength = -1L; @@ -1681,6 +1704,24 @@ public class DefaultServlet return true; } + /** + * Check if the user agent supports gzip encoding. + * + * @param request The servlet request we are processing + * @return boolean true if the user agent supports gzip encoding, + * and false if the user agent does not support gzip encoding + */ + protected boolean checkIfGzip(HttpServletRequest request) { + Enumeration<String> headers = request.getHeaders("Accept-Encoding"); + while (headers.hasMoreElements()) { + String header = headers.nextElement(); + if (header.indexOf("gzip") != -1) { + return true; + } + } + return false; + } + /** * Check if the if-unmodified-since condition is satisfied. Modified: tomcat/trunk/test/org/apache/catalina/servlets/TestDefaultServlet.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/servlets/TestDefaultServlet.java?rev=1531115&r1=1531114&r2=1531115&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/catalina/servlets/TestDefaultServlet.java (original) +++ tomcat/trunk/test/org/apache/catalina/servlets/TestDefaultServlet.java Thu Oct 10 21:24:59 2013 @@ -89,6 +89,56 @@ public class TestDefaultServlet extends } /** + * Verify serving of gzipped resources from context root. + */ + @Test + public void testGzippedFile() throws Exception { + + Tomcat tomcat = getTomcatInstance(); + + File appDir = + new File("test/webapp"); + + File gzipIndex = new File(appDir, "index.html.gz"); + long gzipSize = gzipIndex.length(); + + File index = new File(appDir, "index.html"); + long indexSize = index.length(); + + // app dir is relative to server home + tomcat.addWebapp(null, "", appDir.getAbsolutePath()); + + tomcat.start(); + + TestGzipClient gzipClient = new TestGzipClient(getPort()); + + gzipClient.reset(); + gzipClient.setRequest(new String[] { + "GET /index.html HTTP/1.1" + CRLF + + "Host: localhost" + CRLF + + "Connection: Close" + CRLF + + "Accept-Encoding: gzip" + CRLF + CRLF }); + gzipClient.connect(); + gzipClient.processRequest(); + assertTrue(gzipClient.isResponse200()); + List<String> responseHeaders = gzipClient.getResponseHeaders(); + assertTrue(responseHeaders.contains("Content-Length: " + gzipSize)); + + gzipClient.reset(); + gzipClient.setRequest(new String[] { + "GET /index.html HTTP/1.1" + CRLF + + "Host: localhost" + CRLF + + "Connection: Close" + CRLF+ CRLF }); + gzipClient.connect(); + gzipClient.processRequest(); + assertTrue(gzipClient.isResponse200()); + responseHeaders = gzipClient.getResponseHeaders(); + assertTrue(responseHeaders.contains("Content-Type: text/html")); + assertFalse(responseHeaders.contains("Content-Encoding: gzip")); + assertTrue(responseHeaders.contains("Content-Length: " + indexSize)); + } + + /** * Test https://issues.apache.org/bugzilla/show_bug.cgi?id=50026 * Verify serving of resources from context root with subpath mapping. */ @@ -308,4 +358,16 @@ public class TestDefaultServlet extends return true; } } + + private static class TestGzipClient extends SimpleHttpClient { + + public TestGzipClient(int port) { + setPort(port); + } + + @Override + public boolean isResponseBodyOK() { + return true; + } + } } Added: tomcat/trunk/test/webapp/index.html.gz URL: http://svn.apache.org/viewvc/tomcat/trunk/test/webapp/index.html.gz?rev=1531115&view=auto ============================================================================== Binary file - no diff available. Propchange: tomcat/trunk/test/webapp/index.html.gz ------------------------------------------------------------------------------ svn:mime-type = application/x-gzip Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1531115&r1=1531114&r2=1531115&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Thu Oct 10 21:24:59 2013 @@ -141,6 +141,12 @@ Port storeconfig functionality, which can persist to server.xml and context.xml runtime container configuration changes. (remm) </add> + <add> + <bug>54095</bug>: Add support to the Default Servlet for serving + gzipped versions of static resources directly from disk as an + alternative to Tomcat compressing them on each request. Patch by + Philippe Marschall. (markt) + </add> <fix> <bug>54708</bug>: Change the name of the working directory for the ROOT application (located under $CATALINA_BASE/work by default) from _ to Modified: tomcat/trunk/webapps/docs/default-servlet.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/default-servlet.xml?rev=1531115&r1=1531114&r2=1531115&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/default-servlet.xml (original) +++ tomcat/trunk/webapps/docs/default-servlet.xml Thu Oct 10 21:24:59 2013 @@ -94,6 +94,12 @@ directory listings are disabled and debu expensive. Multiple requests for large directory listings can consume significant proportions of server resources. </property> + <property name="gzip"> + If a gzipped version of a file exists (a file with <code>.gz</code> + appended to the file name located alongside the original file), Tomcat + will serve the gzipped file if the user agent supports gzip and this + option is enabled. [true] + </property> <property name="readmeFile"> If a directory listing is presented, a readme file may also be presented with the listing. This file is inserted as is --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org