436894 GzipFilter code cleanup

This commit is contained in:
Jan Bartel 2014-06-09 18:35:49 +02:00
parent e5910e576e
commit 144a460407
11 changed files with 2248 additions and 13 deletions

View File

@ -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

View File

@ -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"
*
*
* </PRE>
@ -164,6 +171,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
private String _relativeResourceBase;
private ServletHandler _servletHandler;
private ServletHolder _defaultHolder;
private List<String> _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>();
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<String> reqRanges)
{

View File

@ -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()));

View File

@ -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)
{

View File

@ -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()

View File

@ -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();
}
}
}

View File

@ -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.
* <p>
* This is used to test exclusions and passthroughs in the GzipFilter.
* <p>
* 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);
}
}

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -0,0 +1 @@
1ccb7a0b85585d0e9bdc3863ad093d4e53a9ea68 test.svg

Binary file not shown.

View File

@ -0,0 +1 @@
62df7c3ac6ee6e4462b6abf9ef15b4e916ecf68f test.svgz