436894 GzipFilter code cleanup
This commit is contained in:
parent
e5910e576e
commit
144a460407
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 |
|
@ -0,0 +1 @@
|
|||
1ccb7a0b85585d0e9bdc3863ad093d4e53a9ea68 test.svg
|
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
62df7c3ac6ee6e4462b6abf9ef15b4e916ecf68f test.svgz
|
Loading…
Reference in New Issue