Merge branch 'master' of ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project
This commit is contained in:
commit
1843976b30
|
@ -0,0 +1,83 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// All rights reserved. This program and the accompanying materials
|
||||||
|
// are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
// and Apache License v2.0 which accompanies this distribution.
|
||||||
|
//
|
||||||
|
// The Eclipse Public License is available at
|
||||||
|
// http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
//
|
||||||
|
// The Apache License v2.0 is available at
|
||||||
|
// http://www.opensource.org/licenses/apache2.0.php
|
||||||
|
//
|
||||||
|
// You may elect to redistribute this code under either of these licenses.
|
||||||
|
// ========================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
package org.eclipse.jetty.client;
|
||||||
|
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IdleTimeoutTest
|
||||||
|
*
|
||||||
|
* Warning - this is a slow test. Uncomment the ignore to run it.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class IdleTimeoutTest
|
||||||
|
{
|
||||||
|
public int _repetitions = 30;
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
@Test
|
||||||
|
public void testIdleTimeoutOnBlockingConnector() throws Exception
|
||||||
|
{
|
||||||
|
/* TODO port to new client
|
||||||
|
final HttpClient client = new HttpClient();
|
||||||
|
client.setMaxConnectionsPerAddress(4);
|
||||||
|
client.setConnectorType(HttpClient.CONNECTOR_SOCKET);
|
||||||
|
client.setTimeout(TimeUnit.SECONDS.toMillis(86400)); // very long timeout on data
|
||||||
|
client.setIdleTimeout(500); // very short idle timeout
|
||||||
|
client.start();
|
||||||
|
|
||||||
|
final CountDownLatch counter = new CountDownLatch(_repetitions);
|
||||||
|
|
||||||
|
Thread runner = new Thread()
|
||||||
|
{
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (int i=0; i<_repetitions; i++)
|
||||||
|
{
|
||||||
|
ContentExchange exchange = new ContentExchange();
|
||||||
|
exchange.setURL("http://www.google.com/?i="+i);
|
||||||
|
client.send(exchange);
|
||||||
|
exchange.waitForDone();
|
||||||
|
counter.countDown();
|
||||||
|
System.err.println(counter.getCount());
|
||||||
|
Thread.sleep(1000); //wait long enough for idle timeout to expire
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Assert.fail(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
runner.start();
|
||||||
|
if (!counter.await(80, TimeUnit.SECONDS))
|
||||||
|
Assert.fail("Test did not complete in time");
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -255,7 +255,7 @@ public class ShutdownMonitor extends Thread
|
||||||
{
|
{
|
||||||
if (isAlive())
|
if (isAlive())
|
||||||
{
|
{
|
||||||
System.out.printf("ShutdownMonitor already started");
|
System.err.printf("ShutdownMonitor already started");
|
||||||
return; // cannot start it again
|
return; // cannot start it again
|
||||||
}
|
}
|
||||||
startListenSocket();
|
startListenSocket();
|
||||||
|
@ -270,8 +270,9 @@ public class ShutdownMonitor extends Thread
|
||||||
private void startListenSocket()
|
private void startListenSocket()
|
||||||
{
|
{
|
||||||
if (this.port < 0)
|
if (this.port < 0)
|
||||||
{
|
{
|
||||||
System.out.println("ShutdownMonitor not in use (port < 0): " + port);
|
if (DEBUG)
|
||||||
|
System.err.println("ShutdownMonitor not in use (port < 0): " + port);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,15 +104,21 @@ import org.eclipse.jetty.util.log.Logger;
|
||||||
* instead.
|
* instead.
|
||||||
*
|
*
|
||||||
* excludePathPatterns Same as excludePath, but accepts regex patterns for more complex matching.
|
* excludePathPatterns Same as excludePath, but accepts regex patterns for more complex matching.
|
||||||
|
*
|
||||||
|
* vary Set to the value of the Vary header sent with responses that could be compressed. By default it is
|
||||||
|
* set to 'Vary: Accept-Encoding, User-Agent' since IE6 is excluded by default from the excludedAgents.
|
||||||
|
* If user-agents are not to be excluded, then this can be set to 'Vary: Accept-Encoding'. Note also
|
||||||
|
* that shared caches may cache copies of a resource that is varied by User-Agent - one per variation of
|
||||||
|
* the User-Agent, unless the cache does some normalization of the UA string.
|
||||||
* </PRE>
|
* </PRE>
|
||||||
*/
|
*/
|
||||||
public class GzipFilter extends UserAgentFilter
|
public class GzipFilter extends UserAgentFilter
|
||||||
{
|
{
|
||||||
private static final Logger LOG = Log.getLogger(GzipFilter.class);
|
private static final Logger LOG = Log.getLogger(GzipFilter.class);
|
||||||
public final static String GZIP="gzip";
|
public final static String GZIP="gzip";
|
||||||
public final static String ETAG_GZIP="-gzip\"";
|
public final static String ETAG_GZIP="--gzip\"";
|
||||||
public final static String DEFLATE="deflate";
|
public final static String DEFLATE="deflate";
|
||||||
public final static String ETAG_DEFLATE="-deflate\"";
|
public final static String ETAG_DEFLATE="--deflate\"";
|
||||||
public final static String ETAG="o.e.j.s.GzipFilter.ETag";
|
public final static String ETAG="o.e.j.s.GzipFilter.ETag";
|
||||||
|
|
||||||
protected ServletContext _context;
|
protected ServletContext _context;
|
||||||
|
@ -125,6 +131,7 @@ public class GzipFilter extends UserAgentFilter
|
||||||
protected Set<Pattern> _excludedAgentPatterns;
|
protected Set<Pattern> _excludedAgentPatterns;
|
||||||
protected Set<String> _excludedPaths;
|
protected Set<String> _excludedPaths;
|
||||||
protected Set<Pattern> _excludedPathPatterns;
|
protected Set<Pattern> _excludedPathPatterns;
|
||||||
|
protected String _vary="Accept-Encoding, User-Agent";
|
||||||
|
|
||||||
private static final int STATE_SEPARATOR = 0;
|
private static final int STATE_SEPARATOR = 0;
|
||||||
private static final int STATE_Q = 1;
|
private static final int STATE_Q = 1;
|
||||||
|
@ -202,6 +209,10 @@ public class GzipFilter extends UserAgentFilter
|
||||||
while (tok.hasMoreTokens())
|
while (tok.hasMoreTokens())
|
||||||
_excludedPathPatterns.add(Pattern.compile(tok.nextToken()));
|
_excludedPathPatterns.add(Pattern.compile(tok.nextToken()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tmp=filterConfig.getInitParameter("vary");
|
||||||
|
if (tmp!=null)
|
||||||
|
_vary=tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
|
@ -224,9 +235,9 @@ public class GzipFilter extends UserAgentFilter
|
||||||
HttpServletRequest request=(HttpServletRequest)req;
|
HttpServletRequest request=(HttpServletRequest)req;
|
||||||
HttpServletResponse response=(HttpServletResponse)res;
|
HttpServletResponse response=(HttpServletResponse)res;
|
||||||
|
|
||||||
// Exclude URIs - no Vary because no matter what client, this URI is always excluded
|
// If not a GET or an Excluded URI - no Vary because no matter what client, this URI is always excluded
|
||||||
String requestURI = request.getRequestURI();
|
String requestURI = request.getRequestURI();
|
||||||
if (isExcludedPath(requestURI))
|
if (!HttpMethod.GET.is(request.getMethod()) || isExcludedPath(requestURI))
|
||||||
{
|
{
|
||||||
super.doFilter(request,response,chain);
|
super.doFilter(request,response,chain);
|
||||||
return;
|
return;
|
||||||
|
@ -244,54 +255,45 @@ public class GzipFilter extends UserAgentFilter
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inform caches that responses may vary according to Accept-Encoding (this may be nulled later)
|
|
||||||
response.setHeader("Vary","Accept-Encoding");
|
|
||||||
|
|
||||||
// Exclude User-Agents
|
// Excluded User-Agents
|
||||||
String ua = getUserAgent(request);
|
String ua = getUserAgent(request);
|
||||||
String compressionType = selectCompression(request.getHeader("accept-encoding"));
|
boolean ua_excluded=ua!=null&&isExcludedAgent(ua);
|
||||||
|
|
||||||
|
// Acceptable compression type
|
||||||
|
String compressionType = ua_excluded?null:selectCompression(request.getHeader("accept-encoding"));
|
||||||
|
|
||||||
// If this request is not excluded by agent and if it can be compressed
|
// Special handling for etags
|
||||||
if (!isExcludedAgent(ua) && compressionType!=null && !response.containsHeader("Content-Encoding") && !HttpMethod.HEAD.is(request.getMethod()))
|
String etag = request.getHeader("If-None-Match");
|
||||||
|
if (etag!=null)
|
||||||
{
|
{
|
||||||
// Special handling for etags
|
int dd=etag.indexOf("--");
|
||||||
String etag = request.getHeader("If-None-Match");
|
if (dd>0)
|
||||||
if (etag!=null)
|
request.setAttribute(ETAG,etag.substring(0,dd)+(etag.endsWith("\"")?"\"":""));
|
||||||
{
|
|
||||||
if (etag.endsWith(ETAG_GZIP))
|
|
||||||
request.setAttribute(ETAG,etag.substring(0,etag.length()-ETAG_GZIP.length())+'"');
|
|
||||||
else if (etag.endsWith(ETAG_DEFLATE))
|
|
||||||
request.setAttribute(ETAG,etag.substring(0,etag.length()-ETAG_DEFLATE.length())+'"');
|
|
||||||
}
|
|
||||||
|
|
||||||
CompressedResponseWrapper wrappedResponse = createWrappedResponse(request,response,compressionType);
|
|
||||||
|
|
||||||
boolean exceptional=true;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
super.doFilter(request,wrappedResponse,chain);
|
|
||||||
exceptional=false;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Continuation continuation = ContinuationSupport.getContinuation(request);
|
|
||||||
if (continuation.isSuspended() && continuation.isResponseWrapped())
|
|
||||||
{
|
|
||||||
continuation.addContinuationListener(new ContinuationListenerWaitingForWrappedResponseToFinish(wrappedResponse));
|
|
||||||
}
|
|
||||||
else if (exceptional && !response.isCommitted())
|
|
||||||
{
|
|
||||||
wrappedResponse.resetBuffer();
|
|
||||||
wrappedResponse.noCompression();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
wrappedResponse.finish();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
CompressedResponseWrapper wrappedResponse = createWrappedResponse(request,response,compressionType);
|
||||||
|
|
||||||
|
boolean exceptional=true;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
super.doFilter(request,new VaryResponseWrapper(response),chain);
|
super.doFilter(request,wrappedResponse,chain);
|
||||||
|
exceptional=false;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Continuation continuation = ContinuationSupport.getContinuation(request);
|
||||||
|
if (continuation.isSuspended() && continuation.isResponseWrapped())
|
||||||
|
{
|
||||||
|
continuation.addContinuationListener(new ContinuationListenerWaitingForWrappedResponseToFinish(wrappedResponse));
|
||||||
|
}
|
||||||
|
else if (exceptional && !response.isCommitted())
|
||||||
|
{
|
||||||
|
wrappedResponse.resetBuffer();
|
||||||
|
wrappedResponse.noCompression();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
wrappedResponse.finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,14 +389,32 @@ public class GzipFilter extends UserAgentFilter
|
||||||
protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, final String compressionType)
|
protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, final String compressionType)
|
||||||
{
|
{
|
||||||
CompressedResponseWrapper wrappedResponse = null;
|
CompressedResponseWrapper wrappedResponse = null;
|
||||||
if (compressionType.equals(GZIP))
|
if (compressionType==null)
|
||||||
{
|
{
|
||||||
wrappedResponse = new CompressedResponseWrapper(request,response)
|
wrappedResponse = new CompressedResponseWrapper(request,response)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
||||||
{
|
{
|
||||||
return new AbstractCompressedStream(compressionType,request,this)
|
return new AbstractCompressedStream(null,request,this,_vary)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected DeflaterOutputStream createStream() throws IOException
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (compressionType.equals(GZIP))
|
||||||
|
{
|
||||||
|
wrappedResponse = new CompressedResponseWrapper(request,response)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
||||||
|
{
|
||||||
|
return new AbstractCompressedStream(compressionType,request,this,_vary)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected DeflaterOutputStream createStream() throws IOException
|
protected DeflaterOutputStream createStream() throws IOException
|
||||||
|
@ -412,7 +432,7 @@ public class GzipFilter extends UserAgentFilter
|
||||||
@Override
|
@Override
|
||||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
||||||
{
|
{
|
||||||
return new AbstractCompressedStream(compressionType,request,this)
|
return new AbstractCompressedStream(compressionType,request,this,_vary)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected DeflaterOutputStream createStream() throws IOException
|
protected DeflaterOutputStream createStream() throws IOException
|
||||||
|
@ -422,7 +442,7 @@ public class GzipFilter extends UserAgentFilter
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new IllegalStateException(compressionType + " not supported");
|
throw new IllegalStateException(compressionType + " not supported");
|
||||||
|
@ -574,11 +594,8 @@ public class GzipFilter extends UserAgentFilter
|
||||||
ct=ct.substring(0,colon);
|
ct=ct.substring(0,colon);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_mimeTypes!=null && !_mimeTypes.contains(StringUtil.asciiToLowerCase(ct)))
|
if (_mimeTypes!=null && _mimeTypes.contains(StringUtil.asciiToLowerCase(ct)))
|
||||||
// Remove the vary header, because of content type.
|
super.setHeader("Vary",_vary);
|
||||||
super.setHeader("Vary",null);
|
|
||||||
else
|
|
||||||
super.setHeader("Vary","Accept-Encoding");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,14 +70,41 @@ public class IncludableGzipFilter extends GzipFilter
|
||||||
protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, final String compressionType)
|
protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, final String compressionType)
|
||||||
{
|
{
|
||||||
CompressedResponseWrapper wrappedResponse = null;
|
CompressedResponseWrapper wrappedResponse = null;
|
||||||
if (compressionType.equals(GZIP))
|
if (compressionType==null)
|
||||||
{
|
{
|
||||||
wrappedResponse = new IncludableResponseWrapper(request,response)
|
wrappedResponse = new IncludableResponseWrapper(request,response)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
||||||
{
|
{
|
||||||
return new AbstractCompressedStream(compressionType,request,this)
|
return new AbstractCompressedStream(null,request,this,_vary)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected DeflaterOutputStream createStream() throws IOException
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setHeader(String name, String value)
|
||||||
|
{
|
||||||
|
super.setHeader(name, value);
|
||||||
|
HttpServletResponse response = (HttpServletResponse)getResponse();
|
||||||
|
if (!response.containsHeader(name))
|
||||||
|
response.setHeader("org.eclipse.jetty.server.include." + name, value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (compressionType.equals(GZIP))
|
||||||
|
{
|
||||||
|
wrappedResponse = new IncludableResponseWrapper(request,response)
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
||||||
|
{
|
||||||
|
return new AbstractCompressedStream(compressionType,request,this,_vary)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected DeflaterOutputStream createStream() throws IOException
|
protected DeflaterOutputStream createStream() throws IOException
|
||||||
|
@ -104,7 +131,7 @@ public class IncludableGzipFilter extends GzipFilter
|
||||||
@Override
|
@Override
|
||||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
||||||
{
|
{
|
||||||
return new AbstractCompressedStream(compressionType,request,this)
|
return new AbstractCompressedStream(compressionType,request,this,_vary)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected DeflaterOutputStream createStream() throws IOException
|
protected DeflaterOutputStream createStream() throws IOException
|
||||||
|
|
|
@ -40,6 +40,7 @@ import org.eclipse.jetty.util.ByteArrayOutputStream2;
|
||||||
public abstract class AbstractCompressedStream extends ServletOutputStream
|
public abstract class AbstractCompressedStream extends ServletOutputStream
|
||||||
{
|
{
|
||||||
private final String _encoding;
|
private final String _encoding;
|
||||||
|
protected final String _vary;
|
||||||
protected final CompressedResponseWrapper _wrapper;
|
protected final CompressedResponseWrapper _wrapper;
|
||||||
protected final HttpServletResponse _response;
|
protected final HttpServletResponse _response;
|
||||||
protected OutputStream _out;
|
protected OutputStream _out;
|
||||||
|
@ -52,12 +53,13 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
||||||
* Instantiates a new compressed stream.
|
* Instantiates a new compressed stream.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public AbstractCompressedStream(String encoding,HttpServletRequest request, CompressedResponseWrapper wrapper)
|
public AbstractCompressedStream(String encoding,HttpServletRequest request, CompressedResponseWrapper wrapper,String vary)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
_encoding=encoding;
|
_encoding=encoding;
|
||||||
_wrapper = wrapper;
|
_wrapper = wrapper;
|
||||||
_response = (HttpServletResponse)wrapper.getResponse();
|
_response = (HttpServletResponse)wrapper.getResponse();
|
||||||
|
_vary=vary;
|
||||||
|
|
||||||
if (_wrapper.getMinCompressSize()==0)
|
if (_wrapper.getMinCompressSize()==0)
|
||||||
doCompress();
|
doCompress();
|
||||||
|
@ -106,7 +108,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
||||||
{
|
{
|
||||||
long length=_wrapper.getContentLength();
|
long length=_wrapper.getContentLength();
|
||||||
if (length > 0 && length < _wrapper.getMinCompressSize())
|
if (length > 0 && length < _wrapper.getMinCompressSize())
|
||||||
doNotCompress();
|
doNotCompress(false);
|
||||||
else
|
else
|
||||||
doCompress();
|
doCompress();
|
||||||
}
|
}
|
||||||
|
@ -137,13 +139,14 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
||||||
_wrapper.setContentLength(length);
|
_wrapper.setContentLength(length);
|
||||||
}
|
}
|
||||||
if (length < _wrapper.getMinCompressSize())
|
if (length < _wrapper.getMinCompressSize())
|
||||||
doNotCompress();
|
doNotCompress(false);
|
||||||
else
|
else
|
||||||
doCompress();
|
doCompress();
|
||||||
}
|
}
|
||||||
else if (_out == null)
|
else if (_out == null)
|
||||||
{
|
{
|
||||||
doNotCompress();
|
// No output
|
||||||
|
doNotCompress(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_compressedOutputStream != null)
|
if (_compressedOutputStream != null)
|
||||||
|
@ -168,7 +171,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
||||||
{
|
{
|
||||||
long length=_wrapper.getContentLength();
|
long length=_wrapper.getContentLength();
|
||||||
if (length > 0 && length < _wrapper.getMinCompressSize())
|
if (length > 0 && length < _wrapper.getMinCompressSize())
|
||||||
doNotCompress();
|
doNotCompress(false);
|
||||||
else
|
else
|
||||||
doCompress();
|
doCompress();
|
||||||
}
|
}
|
||||||
|
@ -226,23 +229,30 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
||||||
if (_response.isCommitted())
|
if (_response.isCommitted())
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
|
|
||||||
setHeader("Content-Encoding", _encoding);
|
if (_encoding!=null)
|
||||||
if (_response.containsHeader("Content-Encoding"))
|
|
||||||
{
|
{
|
||||||
_out=_compressedOutputStream=createStream();
|
setHeader("Content-Encoding", _encoding);
|
||||||
|
if (_response.containsHeader("Content-Encoding"))
|
||||||
if (_bOut!=null)
|
|
||||||
{
|
{
|
||||||
_out.write(_bOut.getBuf(),0,_bOut.getCount());
|
setHeader("Vary",_vary);
|
||||||
_bOut=null;
|
_out=_compressedOutputStream=createStream();
|
||||||
|
if (_out!=null)
|
||||||
|
{
|
||||||
|
if (_bOut!=null)
|
||||||
|
{
|
||||||
|
_out.write(_bOut.getBuf(),0,_bOut.getCount());
|
||||||
|
_bOut=null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String etag=_wrapper.getETag();
|
||||||
|
if (etag!=null)
|
||||||
|
setHeader("ETag",etag.substring(0,etag.length()-1)+'-'+_encoding+'"');
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String etag=_wrapper.getETag();
|
|
||||||
if (etag!=null)
|
|
||||||
setHeader("ETag",etag.substring(0,etag.length()-1)+'-'+_encoding+'"');
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
doNotCompress();
|
doNotCompress(true); // Send vary as it could have been compressed if encoding was present
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,12 +262,14 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* Signals that an I/O exception has occurred.
|
* Signals that an I/O exception has occurred.
|
||||||
*/
|
*/
|
||||||
public void doNotCompress() throws IOException
|
public void doNotCompress(boolean sendVary) throws IOException
|
||||||
{
|
{
|
||||||
if (_compressedOutputStream != null)
|
if (_compressedOutputStream != null)
|
||||||
throw new IllegalStateException("Compressed output stream is already assigned.");
|
throw new IllegalStateException("Compressed output stream is already assigned.");
|
||||||
if (_out == null || _bOut != null)
|
if (_out == null || _bOut != null)
|
||||||
{
|
{
|
||||||
|
if (sendVary)
|
||||||
|
setHeader("Vary",_vary);
|
||||||
if (_wrapper.getETag()!=null)
|
if (_wrapper.getETag()!=null)
|
||||||
setHeader("ETag",_wrapper.getETag());
|
setHeader("ETag",_wrapper.getETag());
|
||||||
|
|
||||||
|
@ -289,7 +301,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
||||||
{
|
{
|
||||||
long length=_wrapper.getContentLength();
|
long length=_wrapper.getContentLength();
|
||||||
if (_response.isCommitted() || (length >= 0 && length < _wrapper.getMinCompressSize()))
|
if (_response.isCommitted() || (length >= 0 && length < _wrapper.getMinCompressSize()))
|
||||||
doNotCompress();
|
doNotCompress(false);
|
||||||
else if (lengthToWrite > _wrapper.getMinCompressSize())
|
else if (lengthToWrite > _wrapper.getMinCompressSize())
|
||||||
doCompress();
|
doCompress();
|
||||||
else
|
else
|
||||||
|
@ -299,7 +311,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
||||||
{
|
{
|
||||||
long length=_wrapper.getContentLength();
|
long length=_wrapper.getContentLength();
|
||||||
if (_response.isCommitted() || (length >= 0 && length < _wrapper.getMinCompressSize()))
|
if (_response.isCommitted() || (length >= 0 && length < _wrapper.getMinCompressSize()))
|
||||||
doNotCompress();
|
doNotCompress(false);
|
||||||
else if (lengthToWrite >= (_bOut.getBuf().length - _bOut.getCount()))
|
else if (lengthToWrite >= (_bOut.getBuf().length - _bOut.getCount()))
|
||||||
doCompress();
|
doCompress();
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,8 +138,6 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
||||||
(_mimeTypes==null && ct!=null && ct.contains("gzip") ||
|
(_mimeTypes==null && ct!=null && ct.contains("gzip") ||
|
||||||
_mimeTypes!=null && (ct==null||!_mimeTypes.contains(StringUtil.asciiToLowerCase(ct)))))
|
_mimeTypes!=null && (ct==null||!_mimeTypes.contains(StringUtil.asciiToLowerCase(ct)))))
|
||||||
{
|
{
|
||||||
// Remove the vary header, because of content type.
|
|
||||||
setHeader("Vary",null);
|
|
||||||
noCompression();
|
noCompression();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -318,7 +316,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_compressedStream.doNotCompress();
|
_compressedStream.doNotCompress(false);
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,6 +67,7 @@ public class GzipHandler extends HandlerWrapper
|
||||||
protected Set<String> _excluded;
|
protected Set<String> _excluded;
|
||||||
protected int _bufferSize = 8192;
|
protected int _bufferSize = 8192;
|
||||||
protected int _minGzipSize = 256;
|
protected int _minGzipSize = 256;
|
||||||
|
protected String _vary = "Accept-Encoding, User-Agent";
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
/**
|
/**
|
||||||
|
@ -160,6 +161,31 @@ public class GzipHandler extends HandlerWrapper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return The value of the Vary header set if a response can be compressed.
|
||||||
|
*/
|
||||||
|
public String getVary()
|
||||||
|
{
|
||||||
|
return _vary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Set the value of the Vary header sent with responses that could be compressed.
|
||||||
|
* <p>
|
||||||
|
* By default it is set to 'Accept-Encoding, User-Agent' since IE6 is excluded by
|
||||||
|
* default from the excludedAgents. If user-agents are not to be excluded, then
|
||||||
|
* this can be set to 'Accept-Encoding'. Note also that shared caches may cache
|
||||||
|
* many copies of a resource that is varied by User-Agent - one per variation of the
|
||||||
|
* User-Agent, unless the cache does some normalization of the UA string.
|
||||||
|
* @param vary The value of the Vary header set if a response can be compressed.
|
||||||
|
*/
|
||||||
|
public void setVary(String vary)
|
||||||
|
{
|
||||||
|
_vary = vary;
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
/**
|
/**
|
||||||
* Get the buffer size.
|
* Get the buffer size.
|
||||||
|
@ -296,7 +322,7 @@ public class GzipHandler extends HandlerWrapper
|
||||||
@Override
|
@Override
|
||||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
||||||
{
|
{
|
||||||
return new AbstractCompressedStream("gzip",request,this)
|
return new AbstractCompressedStream("gzip",request,this,_vary)
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
protected DeflaterOutputStream createStream() throws IOException
|
protected DeflaterOutputStream createStream() throws IOException
|
||||||
|
|
|
@ -298,6 +298,7 @@ public class GzipTester
|
||||||
private void assertResponseHeaders(int expectedFilesize, int status, HttpTester.Response response)
|
private void assertResponseHeaders(int expectedFilesize, int status, HttpTester.Response response)
|
||||||
{
|
{
|
||||||
Assert.assertThat("Response.status",response.getStatus(),is(status));
|
Assert.assertThat("Response.status",response.getStatus(),is(status));
|
||||||
|
Assert.assertThat("Response.header[Content-Encoding]",response.get("Content-Encoding"),not(containsString(compressionType)));
|
||||||
if (expectedFilesize != (-1))
|
if (expectedFilesize != (-1))
|
||||||
{
|
{
|
||||||
Assert.assertEquals(expectedFilesize,response.getContentBytes().length);
|
Assert.assertEquals(expectedFilesize,response.getContentBytes().length);
|
||||||
|
@ -456,6 +457,7 @@ public class GzipTester
|
||||||
ServletHolder servletHolder = tester.addServlet(servletClass,"/");
|
ServletHolder servletHolder = tester.addServlet(servletClass,"/");
|
||||||
servletHolder.setInitParameter("baseDir",testdir.getDir().getAbsolutePath());
|
servletHolder.setInitParameter("baseDir",testdir.getDir().getAbsolutePath());
|
||||||
FilterHolder holder = tester.addFilter(gzipFilterClass,"/*",EnumSet.allOf(DispatcherType.class));
|
FilterHolder holder = tester.addFilter(gzipFilterClass,"/*",EnumSet.allOf(DispatcherType.class));
|
||||||
|
holder.setInitParameter("vary","Accept-Encoding");
|
||||||
return holder;
|
return holder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -201,6 +201,12 @@
|
||||||
<artifactId>websocket-servlet</artifactId>
|
<artifactId>websocket-servlet</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||||
|
<artifactId>websocket-server</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-webapp</artifactId>
|
<artifactId>jetty-webapp</artifactId>
|
||||||
|
|
Loading…
Reference in New Issue