375692: GzipFilter support for deflate
Change-Id: I4a42d750cfbbb61078adafa1e2bcbc1973198dca
This commit is contained in:
parent
85ade6ae86
commit
2278d27235
|
@ -1,5 +1,5 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) Webtide LLC
|
||||
// Copyright (c) 2009-2009 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
|
||||
|
@ -11,7 +11,6 @@
|
|||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
|
||||
package org.eclipse.jetty.http.gzip;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -28,42 +27,36 @@ import javax.servlet.http.HttpServletResponseWrapper;
|
|||
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*------------------------------------------------------------ */
|
||||
/**
|
||||
* Skeletal implementation of the CompressedResponseWrapper interface.
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper
|
||||
*/
|
||||
public class GzipResponseWrapper extends HttpServletResponseWrapper
|
||||
public abstract class AbstractCompressedResponseWrapper extends HttpServletResponseWrapper implements CompressedResponseWrapper
|
||||
{
|
||||
public static final int DEFAULT_BUFFER_SIZE = 8192;
|
||||
public static final int DEFAULT_MIN_GZIP_SIZE = 256;
|
||||
|
||||
private HttpServletRequest _request;
|
||||
public static final int DEFAULT_BUFFER_SIZE = 8192;
|
||||
public static final int DEFAULT_MIN_COMPRESS_SIZE = 256;
|
||||
|
||||
private Set<String> _mimeTypes;
|
||||
private int _bufferSize=DEFAULT_BUFFER_SIZE;
|
||||
private int _minGzipSize=DEFAULT_MIN_GZIP_SIZE;
|
||||
private int _minCompressSize=DEFAULT_MIN_COMPRESS_SIZE;
|
||||
private HttpServletRequest _request;
|
||||
|
||||
private PrintWriter _writer;
|
||||
private GzipStream _gzStream;
|
||||
private CompressedStream _compressedStream;
|
||||
private long _contentLength=-1;
|
||||
private boolean _noGzip;
|
||||
private boolean _noCompression;
|
||||
|
||||
/**
|
||||
* Instantiates a new gzip response wrapper.
|
||||
*
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
*/
|
||||
public GzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
public AbstractCompressedResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
super(response);
|
||||
_request=request;
|
||||
_request = request;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Sets the mime types.
|
||||
*
|
||||
* @param mimeTypes the new mime types
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setMimeTypes(java.util.Set)
|
||||
*/
|
||||
public void setMimeTypes(Set<String> mimeTypes)
|
||||
{
|
||||
|
@ -72,8 +65,9 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#setBufferSize(int)
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setBufferSize(int)
|
||||
*/
|
||||
@Override
|
||||
public void setBufferSize(int bufferSize)
|
||||
{
|
||||
_bufferSize = bufferSize;
|
||||
|
@ -81,76 +75,77 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Sets the min gzip size.
|
||||
*
|
||||
* @param minGzipSize the new min gzip size
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setMinCompressSize(int)
|
||||
*/
|
||||
public void setMinGzipSize(int minGzipSize)
|
||||
public void setMinCompressSize(int minCompressSize)
|
||||
{
|
||||
_minGzipSize = minGzipSize;
|
||||
_minCompressSize = minCompressSize;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#setContentType(java.lang.String)
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setContentType(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void setContentType(String ct)
|
||||
{
|
||||
super.setContentType(ct);
|
||||
|
||||
|
||||
if (ct!=null)
|
||||
{
|
||||
int colon=ct.indexOf(";");
|
||||
if (colon>0)
|
||||
ct=ct.substring(0,colon);
|
||||
}
|
||||
|
||||
if ((_gzStream==null || _gzStream._out==null) &&
|
||||
|
||||
if ((_compressedStream==null || _compressedStream.getOutputStream()==null) &&
|
||||
(_mimeTypes==null && ct!=null && ct.contains("gzip") ||
|
||||
_mimeTypes!=null && (ct==null||!_mimeTypes.contains(StringUtil.asciiToLowerCase(ct)))))
|
||||
{
|
||||
noGzip();
|
||||
noCompression();
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#setStatus(int, java.lang.String)
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setStatus(int, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void setStatus(int sc, String sm)
|
||||
{
|
||||
super.setStatus(sc,sm);
|
||||
if (sc<200 || sc==204 || sc==205 || sc>=300)
|
||||
noGzip();
|
||||
noCompression();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#setStatus(int)
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setStatus(int)
|
||||
*/
|
||||
@Override
|
||||
public void setStatus(int sc)
|
||||
{
|
||||
super.setStatus(sc);
|
||||
if (sc<200 || sc==204 || sc==205 ||sc>=300)
|
||||
noGzip();
|
||||
noCompression();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#setContentLength(int)
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setContentLength(int)
|
||||
*/
|
||||
@Override
|
||||
public void setContentLength(int length)
|
||||
{
|
||||
setContentLength((long)length);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
protected void setContentLength(long length)
|
||||
{
|
||||
_contentLength=length;
|
||||
if (_gzStream!=null)
|
||||
_gzStream.setContentLength(length);
|
||||
else if (_noGzip && _contentLength>=0)
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.setContentLength(length);
|
||||
else if (_noCompression && _contentLength>=0)
|
||||
{
|
||||
HttpServletResponse response = (HttpServletResponse)getResponse();
|
||||
if(_contentLength<Integer.MAX_VALUE)
|
||||
|
@ -166,15 +161,16 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#addHeader(java.lang.String, java.lang.String)
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#addHeader(java.lang.String, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void addHeader(String name, String value)
|
||||
{
|
||||
if ("content-length".equalsIgnoreCase(name))
|
||||
{
|
||||
_contentLength=Long.parseLong(value);
|
||||
if (_gzStream!=null)
|
||||
_gzStream.setContentLength(_contentLength);
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.setContentLength(_contentLength);
|
||||
}
|
||||
else if ("content-type".equalsIgnoreCase(name))
|
||||
{
|
||||
|
@ -185,7 +181,7 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
|
|||
super.addHeader(name,value);
|
||||
if (!isCommitted())
|
||||
{
|
||||
noGzip();
|
||||
noCompression();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -194,8 +190,119 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#setHeader(java.lang.String, java.lang.String)
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#flushBuffer()
|
||||
*/
|
||||
@Override
|
||||
public void flushBuffer() throws IOException
|
||||
{
|
||||
if (_writer!=null)
|
||||
_writer.flush();
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.finish();
|
||||
else
|
||||
getResponse().flushBuffer();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#reset()
|
||||
*/
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
super.reset();
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.resetBuffer();
|
||||
_writer=null;
|
||||
_compressedStream=null;
|
||||
_noCompression=false;
|
||||
_contentLength=-1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#resetBuffer()
|
||||
*/
|
||||
@Override
|
||||
public void resetBuffer()
|
||||
{
|
||||
super.resetBuffer();
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.resetBuffer();
|
||||
_writer=null;
|
||||
_compressedStream=null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#sendError(int, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void sendError(int sc, String msg) throws IOException
|
||||
{
|
||||
resetBuffer();
|
||||
super.sendError(sc,msg);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#sendError(int)
|
||||
*/
|
||||
@Override
|
||||
public void sendError(int sc) throws IOException
|
||||
{
|
||||
resetBuffer();
|
||||
super.sendError(sc);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#sendRedirect(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void sendRedirect(String location) throws IOException
|
||||
{
|
||||
resetBuffer();
|
||||
super.sendRedirect(location);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#noCompression()
|
||||
*/
|
||||
public void noCompression()
|
||||
{
|
||||
_noCompression=true;
|
||||
if (_compressedStream!=null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_compressedStream.doNotCompress();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#finish()
|
||||
*/
|
||||
public void finish() throws IOException
|
||||
{
|
||||
if (_writer!=null && !_compressedStream.isClosed())
|
||||
_writer.flush();
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.finish();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setHeader(java.lang.String, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void setHeader(String name, String value)
|
||||
{
|
||||
if ("content-length".equalsIgnoreCase(name))
|
||||
|
@ -211,197 +318,77 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
|
|||
super.setHeader(name,value);
|
||||
if (!isCommitted())
|
||||
{
|
||||
noGzip();
|
||||
noCompression();
|
||||
}
|
||||
}
|
||||
else
|
||||
super.setHeader(name,value);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#setIntHeader(java.lang.String, int)
|
||||
*/
|
||||
public void setIntHeader(String name, int value)
|
||||
{
|
||||
if ("content-length".equalsIgnoreCase(name))
|
||||
{
|
||||
_contentLength=value;
|
||||
if (_gzStream!=null)
|
||||
_gzStream.setContentLength(_contentLength);
|
||||
}
|
||||
else
|
||||
super.setIntHeader(name,value);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#flushBuffer()
|
||||
*/
|
||||
public void flushBuffer() throws IOException
|
||||
{
|
||||
if (_writer!=null)
|
||||
_writer.flush();
|
||||
if (_gzStream!=null)
|
||||
_gzStream.finish();
|
||||
else
|
||||
getResponse().flushBuffer();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#reset()
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
super.reset();
|
||||
if (_gzStream!=null)
|
||||
_gzStream.resetBuffer();
|
||||
_writer=null;
|
||||
_gzStream=null;
|
||||
_noGzip=false;
|
||||
_contentLength=-1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#resetBuffer()
|
||||
*/
|
||||
public void resetBuffer()
|
||||
{
|
||||
super.resetBuffer();
|
||||
if (_gzStream!=null)
|
||||
_gzStream.resetBuffer();
|
||||
_writer=null;
|
||||
_gzStream=null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#sendError(int, java.lang.String)
|
||||
*/
|
||||
public void sendError(int sc, String msg) throws IOException
|
||||
{
|
||||
resetBuffer();
|
||||
super.sendError(sc,msg);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#sendError(int)
|
||||
*/
|
||||
public void sendError(int sc) throws IOException
|
||||
{
|
||||
resetBuffer();
|
||||
super.sendError(sc);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#sendRedirect(java.lang.String)
|
||||
*/
|
||||
public void sendRedirect(String location) throws IOException
|
||||
{
|
||||
resetBuffer();
|
||||
super.sendRedirect(location);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#getOutputStream()
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#getOutputStream()
|
||||
*/
|
||||
@Override
|
||||
public ServletOutputStream getOutputStream() throws IOException
|
||||
{
|
||||
if (_gzStream==null)
|
||||
if (_compressedStream==null)
|
||||
{
|
||||
if (getResponse().isCommitted() || _noGzip)
|
||||
if (getResponse().isCommitted() || _noCompression)
|
||||
{
|
||||
setContentLength(_contentLength);
|
||||
return getResponse().getOutputStream();
|
||||
}
|
||||
|
||||
_gzStream=newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize);
|
||||
_compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minCompressSize);
|
||||
}
|
||||
else if (_writer!=null)
|
||||
throw new IllegalStateException("getWriter() called");
|
||||
|
||||
return _gzStream;
|
||||
return (ServletOutputStream)_compressedStream;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#getWriter()
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#getWriter()
|
||||
*/
|
||||
@Override
|
||||
public PrintWriter getWriter() throws IOException
|
||||
{
|
||||
if (_writer==null)
|
||||
{
|
||||
if (_gzStream!=null)
|
||||
if (_compressedStream!=null)
|
||||
throw new IllegalStateException("getOutputStream() called");
|
||||
|
||||
if (getResponse().isCommitted() || _noGzip)
|
||||
if (getResponse().isCommitted() || _noCompression)
|
||||
{
|
||||
setContentLength(_contentLength);
|
||||
return getResponse().getWriter();
|
||||
}
|
||||
|
||||
_gzStream=newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize);
|
||||
_writer=newWriter(_gzStream,getCharacterEncoding());
|
||||
_compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minCompressSize);
|
||||
_writer=newWriter((OutputStream)_compressedStream,getCharacterEncoding());
|
||||
}
|
||||
return _writer;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* No gzip.
|
||||
*/
|
||||
public void noGzip()
|
||||
{
|
||||
_noGzip=true;
|
||||
if (_gzStream!=null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_gzStream.doNotGzip();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Finish.
|
||||
*
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setIntHeader(java.lang.String, int)
|
||||
*/
|
||||
public void finish() throws IOException
|
||||
@Override
|
||||
public void setIntHeader(String name, int value)
|
||||
{
|
||||
if (_writer!=null && !_gzStream._closed)
|
||||
_writer.flush();
|
||||
if (_gzStream!=null)
|
||||
_gzStream.finish();
|
||||
if ("content-length".equalsIgnoreCase(name))
|
||||
{
|
||||
_contentLength=value;
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.setContentLength(_contentLength);
|
||||
}
|
||||
else
|
||||
super.setIntHeader(name,value);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Allows derived implementations to replace GzipStream implementation.
|
||||
*
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
* @param contentLength the content length
|
||||
* @param bufferSize the buffer size
|
||||
* @param minGzipSize the min gzip size
|
||||
* @return the gzip stream
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
protected GzipStream newGzipStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minGzipSize) throws IOException
|
||||
{
|
||||
return new GzipStream(request,response,contentLength,bufferSize,minGzipSize);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Allows derived implementations to replace PrintWriter implementation.
|
||||
|
@ -415,5 +402,11 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
|
|||
{
|
||||
return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*@return the underlying CompressedStream implementation
|
||||
*/
|
||||
protected abstract CompressedStream newCompressedStream(HttpServletRequest _request, HttpServletResponse response, long _contentLength2, int _bufferSize2, int _minCompressedSize2) throws IOException;
|
||||
|
||||
}
|
|
@ -0,0 +1,343 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009-2009 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.http.gzip;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.util.ByteArrayOutputStream2;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Skeletal implementation of a CompressedStream. This class adds compression features to a ServletOutputStream and takes care of setting response headers, etc.
|
||||
* Major work and configuration is done here. Subclasses using different kinds of compression only have to implement the abstract methods doCompress() and
|
||||
* setContentEncoding() using the desired compression and setting the appropiate Content-Encoding header string.
|
||||
*/
|
||||
public abstract class AbstractCompressedStream extends ServletOutputStream implements CompressedStream
|
||||
{
|
||||
protected HttpServletRequest _request;
|
||||
protected HttpServletResponse _response;
|
||||
protected OutputStream _out;
|
||||
protected ByteArrayOutputStream2 _bOut;
|
||||
protected DeflaterOutputStream _compressedOutputStream;
|
||||
protected boolean _closed;
|
||||
protected int _bufferSize;
|
||||
protected int _minCompressSize;
|
||||
protected long _contentLength;
|
||||
protected boolean _doNotCompress;
|
||||
|
||||
/**
|
||||
* Instantiates a new compressed stream.
|
||||
*
|
||||
* @param request
|
||||
* the request
|
||||
* @param response
|
||||
* the response
|
||||
* @param contentLength
|
||||
* the content length
|
||||
* @param bufferSize
|
||||
* the buffer size
|
||||
* @param minCompressSize
|
||||
* the min compress size
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public AbstractCompressedStream(HttpServletRequest request, HttpServletResponse response, long contentLength, int bufferSize, int minCompressSize)
|
||||
throws IOException
|
||||
{
|
||||
_request = request;
|
||||
_response = response;
|
||||
_contentLength = contentLength;
|
||||
_bufferSize = bufferSize;
|
||||
_minCompressSize = minCompressSize;
|
||||
if (minCompressSize == 0)
|
||||
doCompress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset buffer.
|
||||
*/
|
||||
public void resetBuffer()
|
||||
{
|
||||
if (_response.isCommitted())
|
||||
throw new IllegalStateException("Committed");
|
||||
_closed = false;
|
||||
_out = null;
|
||||
_bOut = null;
|
||||
if (_compressedOutputStream != null)
|
||||
_response.setHeader("Content-Encoding",null);
|
||||
_compressedOutputStream = null;
|
||||
_doNotCompress = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content length.
|
||||
*
|
||||
* @param length
|
||||
* the new content length
|
||||
*/
|
||||
public void setContentLength(long length)
|
||||
{
|
||||
_contentLength = length;
|
||||
if (_doNotCompress && length >= 0)
|
||||
{
|
||||
if (_contentLength < Integer.MAX_VALUE)
|
||||
_response.setContentLength((int)_contentLength);
|
||||
else
|
||||
_response.setHeader("Content-Length",Long.toString(_contentLength));
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#flush()
|
||||
*/
|
||||
@Override
|
||||
public void flush() throws IOException
|
||||
{
|
||||
if (_out == null || _bOut != null)
|
||||
{
|
||||
if (_contentLength > 0 && _contentLength < _minCompressSize)
|
||||
doNotCompress();
|
||||
else
|
||||
doCompress();
|
||||
}
|
||||
|
||||
_out.flush();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#close()
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
if (_closed)
|
||||
return;
|
||||
|
||||
if (_request.getAttribute("javax.servlet.include.request_uri") != null)
|
||||
flush();
|
||||
else
|
||||
{
|
||||
if (_bOut != null)
|
||||
{
|
||||
if (_contentLength < 0)
|
||||
_contentLength = _bOut.getCount();
|
||||
if (_contentLength < _minCompressSize)
|
||||
doNotCompress();
|
||||
else
|
||||
doCompress();
|
||||
}
|
||||
else if (_out == null)
|
||||
{
|
||||
doNotCompress();
|
||||
}
|
||||
|
||||
if (_compressedOutputStream != null)
|
||||
_compressedOutputStream.close();
|
||||
else
|
||||
_out.close();
|
||||
_closed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish.
|
||||
*
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void finish() throws IOException
|
||||
{
|
||||
if (!_closed)
|
||||
{
|
||||
if (_out == null || _bOut != null)
|
||||
{
|
||||
if (_contentLength > 0 && _contentLength < _minCompressSize)
|
||||
doNotCompress();
|
||||
else
|
||||
doCompress();
|
||||
}
|
||||
|
||||
if (_compressedOutputStream != null && !_closed)
|
||||
{
|
||||
_closed = true;
|
||||
_compressedOutputStream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#write(int)
|
||||
*/
|
||||
@Override
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
checkOut(1);
|
||||
_out.write(b);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#write(byte[])
|
||||
*/
|
||||
@Override
|
||||
public void write(byte b[]) throws IOException
|
||||
{
|
||||
checkOut(b.length);
|
||||
_out.write(b);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#write(byte[], int, int)
|
||||
*/
|
||||
@Override
|
||||
public void write(byte b[], int off, int len) throws IOException
|
||||
{
|
||||
checkOut(len);
|
||||
_out.write(b,off,len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do compress.
|
||||
*
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void doCompress() throws IOException
|
||||
{
|
||||
if (_compressedOutputStream==null)
|
||||
{
|
||||
if (_response.isCommitted())
|
||||
throw new IllegalStateException();
|
||||
|
||||
if (setContentEncoding())
|
||||
{
|
||||
_out=_compressedOutputStream=createStream();
|
||||
|
||||
if (_bOut!=null)
|
||||
{
|
||||
_out.write(_bOut.getBuf(),0,_bOut.getCount());
|
||||
_bOut=null;
|
||||
}
|
||||
}
|
||||
else
|
||||
doNotCompress();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not compress.
|
||||
*
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void doNotCompress() throws IOException
|
||||
{
|
||||
if (_compressedOutputStream != null)
|
||||
throw new IllegalStateException();
|
||||
if (_out == null || _bOut != null)
|
||||
{
|
||||
_doNotCompress = true;
|
||||
|
||||
_out = _response.getOutputStream();
|
||||
setContentLength(_contentLength);
|
||||
|
||||
if (_bOut != null)
|
||||
_out.write(_bOut.getBuf(),0,_bOut.getCount());
|
||||
_bOut = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check out.
|
||||
*
|
||||
* @param length
|
||||
* the length
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
private void checkOut(int length) throws IOException
|
||||
{
|
||||
if (_closed)
|
||||
throw new IOException("CLOSED");
|
||||
|
||||
if (_out == null)
|
||||
{
|
||||
if (_response.isCommitted() || (_contentLength >= 0 && _contentLength < _minCompressSize))
|
||||
doNotCompress();
|
||||
else if (length > _minCompressSize)
|
||||
doCompress();
|
||||
else
|
||||
_out = _bOut = new ByteArrayOutputStream2(_bufferSize);
|
||||
}
|
||||
else if (_bOut != null)
|
||||
{
|
||||
if (_response.isCommitted() || (_contentLength >= 0 && _contentLength < _minCompressSize))
|
||||
doNotCompress();
|
||||
else if (length >= (_bOut.getBuf().length - _bOut.getCount()))
|
||||
doCompress();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedStream#getOutputStream()
|
||||
*/
|
||||
public OutputStream getOutputStream()
|
||||
{
|
||||
return _out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.http.gzip.CompressedStream#isClosed()
|
||||
*/
|
||||
public boolean isClosed()
|
||||
{
|
||||
return _closed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows derived implementations to replace PrintWriter implementation.
|
||||
*/
|
||||
protected PrintWriter newWriter(OutputStream out, String encoding) throws UnsupportedEncodingException
|
||||
{
|
||||
return encoding == null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content encoding.
|
||||
*
|
||||
* @return true, if successful
|
||||
*/
|
||||
protected abstract boolean setContentEncoding();
|
||||
|
||||
/**
|
||||
* Create the stream fitting to the underlying compression type.
|
||||
*
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
protected abstract DeflaterOutputStream createStream() throws IOException;
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009-2009 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.http.gzip;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* A ResponseWrapper interface that adds compress functionality to a ResponseWrapper
|
||||
*/
|
||||
public interface CompressedResponseWrapper extends HttpServletResponse
|
||||
{
|
||||
|
||||
/**
|
||||
* Sets the mime types.
|
||||
*
|
||||
* @param mimeTypes
|
||||
* the new mime types
|
||||
*/
|
||||
public void setMimeTypes(Set<String> mimeTypes);
|
||||
|
||||
/**
|
||||
* Sets the min compress size.
|
||||
*
|
||||
* @param minCompressSize
|
||||
* the new min compress size
|
||||
*/
|
||||
public void setMinCompressSize(int minCompressSize);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* No compression.
|
||||
*/
|
||||
public void noCompression();
|
||||
|
||||
/**
|
||||
* Finish.
|
||||
*
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void finish() throws IOException;
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009-2009 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.http.gzip;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.Flushable;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Interface for compressed streams
|
||||
*/
|
||||
public interface CompressedStream extends Closeable, Flushable
|
||||
{
|
||||
|
||||
/**
|
||||
* Reset buffer.
|
||||
*/
|
||||
public void resetBuffer();
|
||||
|
||||
/**
|
||||
* Sets the content length.
|
||||
*
|
||||
* @param length
|
||||
* the new content length
|
||||
*/
|
||||
public void setContentLength(long length);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return true if stream is closed
|
||||
*/
|
||||
public boolean isClosed();
|
||||
|
||||
/**
|
||||
* Do compress.
|
||||
*
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void doCompress() throws IOException;
|
||||
|
||||
/**
|
||||
* Do not compress.
|
||||
*
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void doNotCompress() throws IOException;
|
||||
|
||||
/**
|
||||
* Finish.
|
||||
*
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void finish() throws IOException;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return the {@link OutputStream}
|
||||
*/
|
||||
public OutputStream getOutputStream();
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009-2009 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.http.gzip;
|
||||
|
||||
public enum CompressionType
|
||||
{
|
||||
GZIP("gzip"), DEFLATE("deflate"), UNSUPPORTED("unsupported");
|
||||
|
||||
private final String encodingHeader;
|
||||
|
||||
private CompressionType(String encodingHeader)
|
||||
{
|
||||
this.encodingHeader = encodingHeader;
|
||||
}
|
||||
|
||||
public String getEncodingHeader()
|
||||
{
|
||||
return encodingHeader;
|
||||
}
|
||||
|
||||
public static CompressionType getByEncodingHeader(String encodingHeader)
|
||||
{
|
||||
// prefer gzip over deflate
|
||||
if (encodingHeader.toLowerCase().contains(CompressionType.GZIP.encodingHeader))
|
||||
{
|
||||
return CompressionType.GZIP;
|
||||
}
|
||||
else if (encodingHeader.toLowerCase().contains(CompressionType.DEFLATE.encodingHeader))
|
||||
{
|
||||
return CompressionType.DEFLATE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CompressionType.UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) Webtide LLC
|
||||
// ------------------------------------------------------------------------
|
||||
// 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.http.gzip;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
public class DeflateResponseWrapperImpl extends AbstractCompressedResponseWrapper
|
||||
{
|
||||
/**
|
||||
* Instantiates a new deflate response wrapper.
|
||||
*
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
*/
|
||||
public DeflateResponseWrapperImpl(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
super(request,response);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
* @param contentLength the content length
|
||||
* @param bufferSize the buffer size
|
||||
* @param minCompressSize the min compress size
|
||||
* @return the deflate stream
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
@Override
|
||||
protected CompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
|
||||
{
|
||||
return new DeflateStreamImpl(request,response,contentLength,bufferSize,minCompressSize);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) Webtide LLC
|
||||
// ------------------------------------------------------------------------
|
||||
// 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.http.gzip;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Compressed Stream implementation using deflate to compress
|
||||
*/
|
||||
public class DeflateStreamImpl extends AbstractCompressedStream implements CompressedStream
|
||||
{
|
||||
public DeflateStreamImpl(HttpServletRequest request, HttpServletResponse response, long contentLength, int bufferSize, int minGzipSize) throws IOException
|
||||
{
|
||||
super(request,response,contentLength,bufferSize,minGzipSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Content-Encoding header to deflate.
|
||||
*
|
||||
* @return true, if successful
|
||||
*/
|
||||
@Override
|
||||
protected boolean setContentEncoding()
|
||||
{
|
||||
_response.setHeader("Content-Encoding", CompressionType.DEFLATE.getEncodingHeader());
|
||||
return _response.containsHeader("Content-Encoding");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new DeflaterOutputStream backed by _response.getOutputStream()
|
||||
*/
|
||||
@Override
|
||||
protected DeflaterOutputStream createStream() throws IOException
|
||||
{
|
||||
return new DeflaterOutputStream(_response.getOutputStream());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) Webtide LLC
|
||||
// ------------------------------------------------------------------------
|
||||
// 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.http.gzip;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
public class GzipResponseWrapperImpl extends AbstractCompressedResponseWrapper
|
||||
{
|
||||
/**
|
||||
* Instantiates a new gzip response wrapper.
|
||||
*
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
*/
|
||||
public GzipResponseWrapperImpl(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
super(request,response);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
* @param contentLength the content length
|
||||
* @param bufferSize the buffer size
|
||||
* @param minCompressSize the min gzip size
|
||||
* @return the gzip stream
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
@Override
|
||||
protected CompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
|
||||
{
|
||||
return new GzipStreamImpl(request,response,contentLength,bufferSize,minCompressSize);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,305 +0,0 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) Webtide LLC
|
||||
// ------------------------------------------------------------------------
|
||||
// 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.http.gzip;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.util.ByteArrayOutputStream2;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
public class GzipStream extends ServletOutputStream
|
||||
{
|
||||
protected HttpServletRequest _request;
|
||||
protected HttpServletResponse _response;
|
||||
protected OutputStream _out;
|
||||
protected ByteArrayOutputStream2 _bOut;
|
||||
protected GZIPOutputStream _gzOut;
|
||||
protected boolean _closed;
|
||||
protected int _bufferSize;
|
||||
protected int _minGzipSize;
|
||||
protected long _contentLength;
|
||||
protected boolean _doNotGzip;
|
||||
|
||||
/**
|
||||
* Instantiates a new gzip stream.
|
||||
*
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
* @param contentLength the content length
|
||||
* @param bufferSize the buffer size
|
||||
* @param minGzipSize the min gzip size
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public GzipStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minGzipSize) throws IOException
|
||||
{
|
||||
_request=request;
|
||||
_response=response;
|
||||
_contentLength=contentLength;
|
||||
_bufferSize=bufferSize;
|
||||
_minGzipSize=minGzipSize;
|
||||
if (minGzipSize==0)
|
||||
doGzip();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset buffer.
|
||||
*/
|
||||
public void resetBuffer()
|
||||
{
|
||||
if (_response.isCommitted())
|
||||
throw new IllegalStateException("Committed");
|
||||
_closed=false;
|
||||
_out=null;
|
||||
_bOut=null;
|
||||
if (_gzOut!=null)
|
||||
_response.setHeader("Content-Encoding",null);
|
||||
_gzOut=null;
|
||||
_doNotGzip=false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content length.
|
||||
*
|
||||
* @param length the new content length
|
||||
*/
|
||||
public void setContentLength(long length)
|
||||
{
|
||||
_contentLength=length;
|
||||
if (_doNotGzip && length>=0)
|
||||
{
|
||||
if(_contentLength<Integer.MAX_VALUE)
|
||||
_response.setContentLength((int)_contentLength);
|
||||
else
|
||||
_response.setHeader("Content-Length",Long.toString(_contentLength));
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#flush()
|
||||
*/
|
||||
public void flush() throws IOException
|
||||
{
|
||||
if (_out==null || _bOut!=null)
|
||||
{
|
||||
if (_contentLength>0 && _contentLength<_minGzipSize)
|
||||
doNotGzip();
|
||||
else
|
||||
doGzip();
|
||||
}
|
||||
|
||||
_out.flush();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#close()
|
||||
*/
|
||||
public void close() throws IOException
|
||||
{
|
||||
if (_closed)
|
||||
return;
|
||||
|
||||
if (_request.getAttribute("javax.servlet.include.request_uri")!=null)
|
||||
flush();
|
||||
else
|
||||
{
|
||||
if (_bOut!=null)
|
||||
{
|
||||
if (_contentLength<0)
|
||||
_contentLength=_bOut.getCount();
|
||||
if (_contentLength<_minGzipSize)
|
||||
doNotGzip();
|
||||
else
|
||||
doGzip();
|
||||
}
|
||||
else if (_out==null)
|
||||
{
|
||||
doNotGzip();
|
||||
}
|
||||
|
||||
if (_gzOut!=null)
|
||||
_gzOut.close();
|
||||
else
|
||||
_out.close();
|
||||
_closed=true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish.
|
||||
*
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void finish() throws IOException
|
||||
{
|
||||
if (!_closed)
|
||||
{
|
||||
if (_out==null || _bOut!=null)
|
||||
{
|
||||
if (_contentLength>0 && _contentLength<_minGzipSize)
|
||||
doNotGzip();
|
||||
else
|
||||
doGzip();
|
||||
}
|
||||
|
||||
if (_gzOut!=null && !_closed)
|
||||
{
|
||||
_closed=true;
|
||||
_gzOut.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#write(int)
|
||||
*/
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
checkOut(1);
|
||||
_out.write(b);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#write(byte[])
|
||||
*/
|
||||
public void write(byte b[]) throws IOException
|
||||
{
|
||||
checkOut(b.length);
|
||||
_out.write(b);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see java.io.OutputStream#write(byte[], int, int)
|
||||
*/
|
||||
public void write(byte b[], int off, int len) throws IOException
|
||||
{
|
||||
checkOut(len);
|
||||
_out.write(b,off,len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content encoding gzip.
|
||||
*
|
||||
* @return true, if successful
|
||||
*/
|
||||
protected boolean setContentEncodingGzip()
|
||||
{
|
||||
_response.setHeader("Content-Encoding", "gzip");
|
||||
return _response.containsHeader("Content-Encoding");
|
||||
}
|
||||
|
||||
/**
|
||||
* Do gzip.
|
||||
*
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void doGzip() throws IOException
|
||||
{
|
||||
if (_gzOut==null)
|
||||
{
|
||||
if (_response.isCommitted())
|
||||
throw new IllegalStateException();
|
||||
|
||||
if (setContentEncodingGzip())
|
||||
{
|
||||
_out=_gzOut=new GZIPOutputStream(_response.getOutputStream(),_bufferSize);
|
||||
|
||||
if (_bOut!=null)
|
||||
{
|
||||
_out.write(_bOut.getBuf(),0,_bOut.getCount());
|
||||
_bOut=null;
|
||||
}
|
||||
}
|
||||
else
|
||||
doNotGzip();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not gzip.
|
||||
*
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public void doNotGzip() throws IOException
|
||||
{
|
||||
if (_gzOut!=null)
|
||||
throw new IllegalStateException();
|
||||
if (_out==null || _bOut!=null )
|
||||
{
|
||||
_doNotGzip = true;
|
||||
|
||||
_out=_response.getOutputStream();
|
||||
setContentLength(_contentLength);
|
||||
|
||||
if (_bOut!=null)
|
||||
_out.write(_bOut.getBuf(),0,_bOut.getCount());
|
||||
_bOut=null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check out.
|
||||
*
|
||||
* @param length the length
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
private void checkOut(int length) throws IOException
|
||||
{
|
||||
if (_closed)
|
||||
throw new IOException("CLOSED");
|
||||
|
||||
if (_out==null)
|
||||
{
|
||||
if (_response.isCommitted() || (_contentLength>=0 && _contentLength<_minGzipSize))
|
||||
doNotGzip();
|
||||
else if (length>_minGzipSize)
|
||||
doGzip();
|
||||
else
|
||||
_out=_bOut=new ByteArrayOutputStream2(_bufferSize);
|
||||
}
|
||||
else if (_bOut!=null)
|
||||
{
|
||||
if (_response.isCommitted() || (_contentLength>=0 && _contentLength<_minGzipSize))
|
||||
doNotGzip();
|
||||
else if (length>=(_bOut.getBuf().length -_bOut.getCount()))
|
||||
doGzip();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows derived implementations to replace PrintWriter implementation.
|
||||
*/
|
||||
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
|
||||
{
|
||||
return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) Webtide LLC
|
||||
// ------------------------------------------------------------------------
|
||||
// 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.http.gzip;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Compressed Stream implementation using gzip to compress
|
||||
*/
|
||||
public class GzipStreamImpl extends AbstractCompressedStream implements CompressedStream
|
||||
{
|
||||
public GzipStreamImpl(HttpServletRequest request, HttpServletResponse response, long contentLength, int bufferSize, int minGzipSize) throws IOException
|
||||
{
|
||||
super(request,response,contentLength,bufferSize,minGzipSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Content-Encoding header to gzip.
|
||||
*
|
||||
* @return true, if successful
|
||||
*/
|
||||
@Override
|
||||
protected boolean setContentEncoding()
|
||||
{
|
||||
_response.setHeader("Content-Encoding", CompressionType.GZIP.getEncodingHeader());
|
||||
return _response.containsHeader("Content-Encoding");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a new GZIPOutputStream backed by _response.getOutputStream()
|
||||
*/
|
||||
@Override
|
||||
protected DeflaterOutputStream createStream() throws IOException
|
||||
{
|
||||
return new GZIPOutputStream(_response.getOutputStream(),_bufferSize);
|
||||
}
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ import org.eclipse.jetty.continuation.Continuation;
|
|||
import org.eclipse.jetty.continuation.ContinuationListener;
|
||||
import org.eclipse.jetty.continuation.ContinuationSupport;
|
||||
import org.eclipse.jetty.http.HttpMethods;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapperImpl;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -222,7 +222,7 @@ public class GzipHandler extends HandlerWrapper
|
|||
}
|
||||
}
|
||||
|
||||
final GzipResponseWrapper wrappedResponse = newGzipResponseWrapper(request,response);
|
||||
final GzipResponseWrapperImpl wrappedResponse = newGzipResponseWrapper(request,response);
|
||||
|
||||
boolean exceptional=true;
|
||||
try
|
||||
|
@ -256,7 +256,7 @@ public class GzipHandler extends HandlerWrapper
|
|||
else if (exceptional && !response.isCommitted())
|
||||
{
|
||||
wrappedResponse.resetBuffer();
|
||||
wrappedResponse.noGzip();
|
||||
wrappedResponse.noCompression();
|
||||
}
|
||||
else
|
||||
wrappedResponse.finish();
|
||||
|
@ -276,14 +276,14 @@ public class GzipHandler extends HandlerWrapper
|
|||
* @param response the response
|
||||
* @return the gzip response wrapper
|
||||
*/
|
||||
protected GzipResponseWrapper newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
protected GzipResponseWrapperImpl newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
return new GzipResponseWrapper(request, response)
|
||||
return new GzipResponseWrapperImpl(request, response)
|
||||
{
|
||||
{
|
||||
super.setMimeTypes(GzipHandler.this._mimeTypes);
|
||||
super.setBufferSize(GzipHandler.this._bufferSize);
|
||||
super.setMinGzipSize(GzipHandler.this._minGzipSize);
|
||||
super.setMinCompressSize(GzipHandler.this._minGzipSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -13,10 +13,6 @@
|
|||
package org.eclipse.jetty.servlets;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
@ -34,14 +30,18 @@ import org.eclipse.jetty.continuation.Continuation;
|
|||
import org.eclipse.jetty.continuation.ContinuationListener;
|
||||
import org.eclipse.jetty.continuation.ContinuationSupport;
|
||||
import org.eclipse.jetty.http.HttpMethods;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
|
||||
import org.eclipse.jetty.http.gzip.CompressedResponseWrapper;
|
||||
import org.eclipse.jetty.http.gzip.CompressionType;
|
||||
import org.eclipse.jetty.http.gzip.DeflateResponseWrapperImpl;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapperImpl;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** GZIP Filter
|
||||
* This filter will gzip the content of a response iff: <ul>
|
||||
* This filter will gzip or deflate the content of a response if: <ul>
|
||||
* <li>The filter is mapped to a matching path</li>
|
||||
* <li>accept-encoding header is set to either gzip, deflate or a combination of those</li>
|
||||
* <li>The response status code is >=200 and <300
|
||||
* <li>The content length is unknown or more than the <code>minGzipSize</code> initParameter or the minGzipSize is 0(default)</li>
|
||||
* <li>The content-type is in the comma separated list of mimeTypes set in the <code>mimeTypes</code> initParameter or
|
||||
|
@ -50,8 +50,11 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* If both gzip and deflate are specified in the accept-encoding header, then gzip will be used.
|
||||
* </p>
|
||||
* <p>
|
||||
* Compressing the content can greatly improve the network bandwidth usage, but at a cost of memory and
|
||||
* CPU cycles. If this filter is mapped for static content, then use of efficient direct NIO may be
|
||||
* CPU cycles. If this filter is mapped for static content, then use of efficient direct NIO may be
|
||||
* prevented, thus use of the gzip mechanism of the {@link org.eclipse.jetty.servlet.DefaultServlet} is
|
||||
* advised instead.
|
||||
* </p>
|
||||
|
@ -157,7 +160,8 @@ public class GzipFilter extends UserAgentFilter
|
|||
HttpServletResponse response=(HttpServletResponse)res;
|
||||
|
||||
String ae = request.getHeader("accept-encoding");
|
||||
if (ae != null && ae.indexOf("gzip")>=0 && !response.containsHeader("Content-Encoding")
|
||||
CompressionType compressionType = CompressionType.getByEncodingHeader(ae);
|
||||
if (ae != null && !compressionType.equals(CompressionType.UNSUPPORTED) && !response.containsHeader("Content-Encoding")
|
||||
&& !HttpMethods.HEAD.equalsIgnoreCase(request.getMethod()))
|
||||
{
|
||||
String ua = getUserAgent(request);
|
||||
|
@ -172,8 +176,8 @@ public class GzipFilter extends UserAgentFilter
|
|||
super.doFilter(request,response,chain);
|
||||
return;
|
||||
}
|
||||
|
||||
final GzipResponseWrapper wrappedResponse=newGzipResponseWrapper(request,response);
|
||||
|
||||
CompressedResponseWrapper wrappedResponse = createWrappedResponse(request,response,compressionType);
|
||||
|
||||
boolean exceptional=true;
|
||||
try
|
||||
|
@ -186,28 +190,12 @@ public class GzipFilter extends UserAgentFilter
|
|||
Continuation continuation = ContinuationSupport.getContinuation(request);
|
||||
if (continuation.isSuspended() && continuation.isResponseWrapped())
|
||||
{
|
||||
continuation.addContinuationListener(new ContinuationListener()
|
||||
{
|
||||
public void onComplete(Continuation continuation)
|
||||
{
|
||||
try
|
||||
{
|
||||
wrappedResponse.finish();
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void onTimeout(Continuation continuation)
|
||||
{}
|
||||
});
|
||||
continuation.addContinuationListener(new ContinuationListenerWaitingForWrappedResponseToFinish(wrappedResponse));
|
||||
}
|
||||
else if (exceptional && !response.isCommitted())
|
||||
{
|
||||
wrappedResponse.resetBuffer();
|
||||
wrappedResponse.noGzip();
|
||||
wrappedResponse.noCompression();
|
||||
}
|
||||
else
|
||||
wrappedResponse.finish();
|
||||
|
@ -218,7 +206,59 @@ public class GzipFilter extends UserAgentFilter
|
|||
super.doFilter(request,response,chain);
|
||||
}
|
||||
}
|
||||
|
||||
protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, CompressionType compressionType)
|
||||
{
|
||||
CompressedResponseWrapper wrappedResponse = null;
|
||||
if (compressionType.equals(CompressionType.GZIP))
|
||||
{
|
||||
wrappedResponse = new GzipResponseWrapperImpl(request,response);
|
||||
}
|
||||
else if (compressionType.equals(CompressionType.DEFLATE))
|
||||
{
|
||||
wrappedResponse = new DeflateResponseWrapperImpl(request,response);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException(compressionType + " not supported");
|
||||
}
|
||||
configureWrappedResponse(wrappedResponse);
|
||||
return wrappedResponse;
|
||||
}
|
||||
|
||||
private void configureWrappedResponse(CompressedResponseWrapper wrappedResponse)
|
||||
{
|
||||
wrappedResponse.setMimeTypes(_mimeTypes);
|
||||
wrappedResponse.setBufferSize(_bufferSize);
|
||||
wrappedResponse.setMinCompressSize(_minGzipSize);
|
||||
}
|
||||
|
||||
private class ContinuationListenerWaitingForWrappedResponseToFinish implements ContinuationListener{
|
||||
|
||||
private CompressedResponseWrapper wrappedResponse;
|
||||
|
||||
public ContinuationListenerWaitingForWrappedResponseToFinish(CompressedResponseWrapper wrappedResponse)
|
||||
{
|
||||
this.wrappedResponse = wrappedResponse;
|
||||
}
|
||||
|
||||
public void onComplete(Continuation continuation)
|
||||
{
|
||||
try
|
||||
{
|
||||
wrappedResponse.finish();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void onTimeout(Continuation continuation)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the UserAgent is excluded
|
||||
*
|
||||
|
@ -275,42 +315,4 @@ public class GzipFilter extends UserAgentFilter
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows derived implementations to replace ResponseWrapper implementation.
|
||||
*
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
* @return the gzip response wrapper
|
||||
*/
|
||||
protected GzipResponseWrapper newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
return new GzipResponseWrapper(request, response)
|
||||
{
|
||||
{
|
||||
setMimeTypes(GzipFilter.this._mimeTypes);
|
||||
setBufferSize(GzipFilter.this._bufferSize);
|
||||
setMinGzipSize(GzipFilter.this._minGzipSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
|
||||
{
|
||||
return GzipFilter.this.newWriter(out,encoding);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows derived implementations to replace PrintWriter implementation.
|
||||
*
|
||||
* @param out the out
|
||||
* @param encoding the encoding
|
||||
* @return the prints the writer
|
||||
* @throws UnsupportedEncodingException
|
||||
*/
|
||||
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
|
||||
{
|
||||
return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,12 +24,14 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
|
||||
import org.eclipse.jetty.http.gzip.GzipStream;
|
||||
import org.eclipse.jetty.http.gzip.CompressedResponseWrapper;
|
||||
import org.eclipse.jetty.http.gzip.CompressedStream;
|
||||
import org.eclipse.jetty.http.gzip.CompressionType;
|
||||
import org.eclipse.jetty.http.gzip.DeflateStreamImpl;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapperImpl;
|
||||
import org.eclipse.jetty.http.gzip.GzipStreamImpl;
|
||||
import org.eclipse.jetty.io.UncheckedPrintWriter;
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Includable GZip Filter.
|
||||
* This extension to the {@link GzipFilter} that uses Jetty features to allow
|
||||
|
@ -57,36 +59,52 @@ public class IncludableGzipFilter extends GzipFilter
|
|||
}
|
||||
|
||||
@Override
|
||||
protected GzipResponseWrapper newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, CompressionType compressionType)
|
||||
{
|
||||
return new IncludableResponseWrapper(request,response);
|
||||
}
|
||||
|
||||
public class IncludableResponseWrapper extends GzipResponseWrapper
|
||||
public class IncludableResponseWrapper extends GzipResponseWrapperImpl
|
||||
{
|
||||
public IncludableResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
super(request,response);
|
||||
|
||||
|
||||
super.setMimeTypes(IncludableGzipFilter.this._mimeTypes);
|
||||
super.setBufferSize(IncludableGzipFilter.this._bufferSize);
|
||||
super.setMinGzipSize(IncludableGzipFilter.this._minGzipSize);
|
||||
super.setMinCompressSize(IncludableGzipFilter.this._minGzipSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GzipStream newGzipStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minGzipSize) throws IOException
|
||||
protected CompressedStream newCompressedStream(HttpServletRequest request, HttpServletResponse response, long contentLength, int bufferSize,
|
||||
int minGzipSize) throws IOException
|
||||
{
|
||||
return new IncludableGzipStream(request,response,contentLength,bufferSize,minGzipSize);
|
||||
String encodingHeader = request.getHeader("accept-encoding");
|
||||
CompressionType compressionType = CompressionType.getByEncodingHeader(encodingHeader);
|
||||
if (compressionType.equals(CompressionType.GZIP))
|
||||
{
|
||||
return new IncludableGzipStream(request,response,contentLength,bufferSize,minGzipSize);
|
||||
}
|
||||
else if (compressionType.equals(CompressionType.DEFLATE))
|
||||
{
|
||||
return new IncludableDeflateStream(request,response,contentLength,bufferSize,minGzipSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException(compressionType.name() + " not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
|
||||
protected PrintWriter newWriter(OutputStream out, String encoding) throws UnsupportedEncodingException
|
||||
{
|
||||
return IncludableGzipFilter.this.newWriter(out,encoding);
|
||||
if (_uncheckedPrintWriter)
|
||||
return encoding == null?new UncheckedPrintWriter(out):new UncheckedPrintWriter(new OutputStreamWriter(out,encoding));
|
||||
return super.newWriter(out,encoding);
|
||||
}
|
||||
}
|
||||
|
||||
public class IncludableGzipStream extends GzipStream
|
||||
|
||||
public class IncludableGzipStream extends GzipStreamImpl
|
||||
{
|
||||
public IncludableGzipStream(HttpServletRequest request, HttpServletResponse response, long contentLength, int bufferSize, int minGzipSize)
|
||||
throws IOException
|
||||
|
@ -95,22 +113,43 @@ public class IncludableGzipFilter extends GzipFilter
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean setContentEncodingGzip()
|
||||
protected boolean setContentEncoding()
|
||||
{
|
||||
if (_request.getAttribute("javax.servlet.include.request_uri")!=null)
|
||||
_response.setHeader("org.eclipse.jetty.server.include.Content-Encoding", "gzip");
|
||||
if (_request.getAttribute("javax.servlet.include.request_uri") != null)
|
||||
{
|
||||
_response.setHeader("org.eclipse.jetty.server.include.Content-Encoding","gzip");
|
||||
}
|
||||
else
|
||||
_response.setHeader("Content-Encoding", "gzip");
|
||||
|
||||
{
|
||||
_response.setHeader("Content-Encoding","gzip");
|
||||
}
|
||||
|
||||
return _response.containsHeader("Content-Encoding");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
|
||||
public class IncludableDeflateStream extends DeflateStreamImpl
|
||||
{
|
||||
if (_uncheckedPrintWriter)
|
||||
return encoding==null?new UncheckedPrintWriter(out):new UncheckedPrintWriter(new OutputStreamWriter(out,encoding));
|
||||
return super.newWriter(out,encoding);
|
||||
public IncludableDeflateStream(HttpServletRequest request, HttpServletResponse response, long contentLength, int bufferSize, int minGzipSize)
|
||||
throws IOException
|
||||
{
|
||||
super(request,response,contentLength,bufferSize,minGzipSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setContentEncoding()
|
||||
{
|
||||
if (_request.getAttribute("javax.servlet.include.request_uri") != null)
|
||||
{
|
||||
_response.setHeader("org.eclipse.jetty.server.include.Content-Encoding","deflate");
|
||||
}
|
||||
else
|
||||
{
|
||||
_response.setHeader("Content-Encoding","deflate");
|
||||
}
|
||||
|
||||
return _response.containsHeader("Content-Encoding");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@ import java.util.List;
|
|||
import javax.servlet.Servlet;
|
||||
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
|
||||
import org.eclipse.jetty.http.gzip.CompressionType;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapperImpl;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlets.gzip.GzipTester;
|
||||
import org.eclipse.jetty.servlets.gzip.TestServletLengthStreamTypeWrite;
|
||||
|
@ -48,32 +49,42 @@ public class GzipFilterContentLengthTest
|
|||
{
|
||||
return Arrays.asList(new Object[][]
|
||||
{
|
||||
{ TestServletLengthStreamTypeWrite.class },
|
||||
{ TestServletLengthTypeStreamWrite.class },
|
||||
{ TestServletStreamLengthTypeWrite.class },
|
||||
{ TestServletStreamTypeLengthWrite.class },
|
||||
{ TestServletTypeLengthStreamWrite.class },
|
||||
{ TestServletTypeStreamLengthWrite.class } });
|
||||
{ TestServletLengthStreamTypeWrite.class, CompressionType.GZIP },
|
||||
{ TestServletLengthTypeStreamWrite.class, CompressionType.GZIP },
|
||||
{ TestServletStreamLengthTypeWrite.class, CompressionType.GZIP },
|
||||
{ TestServletStreamTypeLengthWrite.class, CompressionType.GZIP },
|
||||
{ TestServletTypeLengthStreamWrite.class, CompressionType.GZIP },
|
||||
{ TestServletTypeStreamLengthWrite.class, CompressionType.GZIP },
|
||||
{ TestServletLengthStreamTypeWrite.class, CompressionType.DEFLATE },
|
||||
{ TestServletLengthTypeStreamWrite.class, CompressionType.DEFLATE },
|
||||
{ TestServletStreamLengthTypeWrite.class, CompressionType.DEFLATE },
|
||||
{ TestServletStreamTypeLengthWrite.class, CompressionType.DEFLATE },
|
||||
{ TestServletTypeLengthStreamWrite.class, CompressionType.DEFLATE },
|
||||
{ TestServletTypeStreamLengthWrite.class, CompressionType.DEFLATE }
|
||||
});
|
||||
}
|
||||
|
||||
private static final int LARGE = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 8;
|
||||
private static final int MEDIUM = GzipResponseWrapper.DEFAULT_BUFFER_SIZE;
|
||||
private static final int SMALL = GzipResponseWrapper.DEFAULT_BUFFER_SIZE / 4;
|
||||
private static final int TINY = GzipResponseWrapper.DEFAULT_MIN_GZIP_SIZE / 2;
|
||||
private static final int LARGE = GzipResponseWrapperImpl.DEFAULT_BUFFER_SIZE * 8;
|
||||
private static final int MEDIUM = GzipResponseWrapperImpl.DEFAULT_BUFFER_SIZE;
|
||||
private static final int SMALL = GzipResponseWrapperImpl.DEFAULT_BUFFER_SIZE / 4;
|
||||
private static final int TINY = GzipResponseWrapperImpl.DEFAULT_MIN_COMPRESS_SIZE/ 2;
|
||||
|
||||
private CompressionType compressionType;
|
||||
|
||||
public GzipFilterContentLengthTest(Class<? extends Servlet> testServlet, CompressionType compressionType)
|
||||
{
|
||||
this.testServlet = testServlet;
|
||||
this.compressionType = compressionType;
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestingDir testingdir = new TestingDir();
|
||||
|
||||
private Class<? extends Servlet> testServlet;
|
||||
|
||||
public GzipFilterContentLengthTest(Class<? extends Servlet> testServlet)
|
||||
{
|
||||
this.testServlet = testServlet;
|
||||
}
|
||||
|
||||
private void assertIsGzipCompressed(String filename, int filesize) throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
File testfile = tester.prepareServerFile(testServlet.getSimpleName() + "-" + filename,filesize);
|
||||
|
||||
|
@ -93,7 +104,7 @@ public class GzipFilterContentLengthTest
|
|||
|
||||
private void assertIsNotGzipCompressed(String filename, int filesize) throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
File testfile = tester.prepareServerFile(testServlet.getSimpleName() + "-" + filename,filesize);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import java.io.IOException;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.http.gzip.CompressionType;
|
||||
import org.eclipse.jetty.servlet.DefaultServlet;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlets.gzip.GzipTester;
|
||||
|
@ -31,22 +32,41 @@ public class GzipFilterDefaultNoRecompressTest
|
|||
return Arrays.asList(new Object[][]
|
||||
{
|
||||
// Some already compressed files
|
||||
{ "test_quotes.gz", "application/gzip" },
|
||||
{ "test_quotes.bz2", "application/bzip2" },
|
||||
{ "test_quotes.zip", "application/zip" },
|
||||
{ "test_quotes.rar", "application/octet-stream" },
|
||||
{ "test_quotes.gz", "application/gzip", CompressionType.GZIP },
|
||||
{ "test_quotes.bz2", "application/bzip2", CompressionType.GZIP },
|
||||
{ "test_quotes.zip", "application/zip", CompressionType.GZIP },
|
||||
{ "test_quotes.rar", "application/octet-stream", CompressionType.GZIP },
|
||||
// Some images (common first)
|
||||
{ "jetty_logo.png", "image/png" },
|
||||
{ "jetty_logo.gif", "image/gif" },
|
||||
{ "jetty_logo.jpeg", "image/jpeg" },
|
||||
{ "jetty_logo.jpg", "image/jpeg" },
|
||||
{ "jetty_logo.png", "image/png", CompressionType.GZIP },
|
||||
{ "jetty_logo.gif", "image/gif", CompressionType.GZIP },
|
||||
{ "jetty_logo.jpeg", "image/jpeg", CompressionType.GZIP },
|
||||
{ "jetty_logo.jpg", "image/jpeg", CompressionType.GZIP },
|
||||
// Lesser encountered images (usually found being requested from non-browser clients)
|
||||
{ "jetty_logo.bmp", "image/bmp" },
|
||||
{ "jetty_logo.tga", "application/tga" },
|
||||
{ "jetty_logo.tif", "image/tiff" },
|
||||
{ "jetty_logo.tiff", "image/tiff" },
|
||||
{ "jetty_logo.xcf", "image/xcf" },
|
||||
{ "jetty_logo.jp2", "image/jpeg2000" } });
|
||||
{ "jetty_logo.bmp", "image/bmp", CompressionType.GZIP },
|
||||
{ "jetty_logo.tga", "application/tga", CompressionType.GZIP },
|
||||
{ "jetty_logo.tif", "image/tiff", CompressionType.GZIP },
|
||||
{ "jetty_logo.tiff", "image/tiff", CompressionType.GZIP },
|
||||
{ "jetty_logo.xcf", "image/xcf", CompressionType.GZIP },
|
||||
{ "jetty_logo.jp2", "image/jpeg2000", CompressionType.GZIP },
|
||||
|
||||
// Same tests again for deflate
|
||||
// Some already compressed files
|
||||
{ "test_quotes.gz", "application/gzip", CompressionType.DEFLATE },
|
||||
{ "test_quotes.bz2", "application/bzip2", CompressionType.DEFLATE },
|
||||
{ "test_quotes.zip", "application/zip", CompressionType.DEFLATE },
|
||||
{ "test_quotes.rar", "application/octet-stream", CompressionType.DEFLATE },
|
||||
// Some images (common first)
|
||||
{ "jetty_logo.png", "image/png", CompressionType.DEFLATE },
|
||||
{ "jetty_logo.gif", "image/gif", CompressionType.DEFLATE },
|
||||
{ "jetty_logo.jpeg", "image/jpeg", CompressionType.DEFLATE },
|
||||
{ "jetty_logo.jpg", "image/jpeg", CompressionType.DEFLATE },
|
||||
// Lesser encountered images (usually found being requested from non-browser clients)
|
||||
{ "jetty_logo.bmp", "image/bmp", CompressionType.DEFLATE },
|
||||
{ "jetty_logo.tga", "application/tga", CompressionType.DEFLATE },
|
||||
{ "jetty_logo.tif", "image/tiff", CompressionType.DEFLATE },
|
||||
{ "jetty_logo.tiff", "image/tiff", CompressionType.DEFLATE },
|
||||
{ "jetty_logo.xcf", "image/xcf", CompressionType.DEFLATE },
|
||||
{ "jetty_logo.jp2", "image/jpeg2000", CompressionType.DEFLATE } });
|
||||
}
|
||||
|
||||
@Rule
|
||||
|
@ -54,17 +74,19 @@ public class GzipFilterDefaultNoRecompressTest
|
|||
|
||||
private String alreadyCompressedFilename;
|
||||
private String expectedContentType;
|
||||
private CompressionType compressionType;
|
||||
|
||||
public GzipFilterDefaultNoRecompressTest(String testFilename, String expectedContentType)
|
||||
public GzipFilterDefaultNoRecompressTest(String testFilename, String expectedContentType, CompressionType compressionType)
|
||||
{
|
||||
this.alreadyCompressedFilename = testFilename;
|
||||
this.expectedContentType = expectedContentType;
|
||||
this.compressionType = compressionType;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotGzipFiltered_Default_AlreadyCompressed() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
copyTestFileToServer(alreadyCompressedFilename);
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package org.eclipse.jetty.servlets;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
|
@ -8,23 +10,48 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
|
||||
import org.eclipse.jetty.http.gzip.CompressionType;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapperImpl;
|
||||
import org.eclipse.jetty.servlet.DefaultServlet;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlets.gzip.GzipTester;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
/**
|
||||
* Test the GzipFilter support built into the {@link DefaultServlet}
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class GzipFilterDefaultTest
|
||||
{
|
||||
@Parameters
|
||||
public static Collection<CompressionType[]> data()
|
||||
{
|
||||
CompressionType[][] data = new CompressionType[][]
|
||||
{
|
||||
{ CompressionType.GZIP },
|
||||
{ CompressionType.DEFLATE }
|
||||
};
|
||||
|
||||
return Arrays.asList(data);
|
||||
}
|
||||
|
||||
private CompressionType compressionType;
|
||||
|
||||
public GzipFilterDefaultTest(CompressionType compressionType)
|
||||
{
|
||||
this.compressionType = compressionType;
|
||||
}
|
||||
|
||||
|
||||
public static class HttpStatusServlet extends HttpServlet
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int _status = 204;
|
||||
|
||||
public HttpStatusServlet()
|
||||
|
@ -50,10 +77,10 @@ public class GzipFilterDefaultTest
|
|||
@Test
|
||||
public void testIsGzipCompressedTiny() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
// Test content that is smaller than the buffer.
|
||||
int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE / 4;
|
||||
int filesize = GzipResponseWrapperImpl.DEFAULT_BUFFER_SIZE / 4;
|
||||
tester.prepareServerFile("file.txt",filesize);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(org.eclipse.jetty.servlet.DefaultServlet.class);
|
||||
|
@ -73,10 +100,10 @@ public class GzipFilterDefaultTest
|
|||
@Test
|
||||
public void testIsGzipCompressedLarge() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
// Test content that is smaller than the buffer.
|
||||
int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
|
||||
int filesize = GzipResponseWrapperImpl.DEFAULT_BUFFER_SIZE * 4;
|
||||
tester.prepareServerFile("file.txt",filesize);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(org.eclipse.jetty.servlet.DefaultServlet.class);
|
||||
|
@ -96,10 +123,10 @@ public class GzipFilterDefaultTest
|
|||
@Test
|
||||
public void testIsNotGzipCompressed() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
// Test content that is smaller than the buffer.
|
||||
int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
|
||||
int filesize = GzipResponseWrapperImpl.DEFAULT_BUFFER_SIZE * 4;
|
||||
tester.prepareServerFile("file.mp3",filesize);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(org.eclipse.jetty.servlet.DefaultServlet.class);
|
||||
|
@ -119,7 +146,7 @@ public class GzipFilterDefaultTest
|
|||
@Test
|
||||
public void testIsNotGzipCompressedHttpStatus() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
// Test error code 204
|
||||
FilterHolder holder = tester.setContentServlet(HttpStatusServlet.class);
|
||||
|
@ -140,13 +167,13 @@ public class GzipFilterDefaultTest
|
|||
@Test
|
||||
public void testUserAgentExclusion() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir);
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(DefaultServlet.class);
|
||||
holder.setInitParameter("excludedAgents", "foo");
|
||||
tester.setUserAgent("foo");
|
||||
|
||||
int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
|
||||
int filesize = GzipResponseWrapperImpl.DEFAULT_BUFFER_SIZE * 4;
|
||||
tester.prepareServerFile("file.txt",filesize);
|
||||
|
||||
try
|
||||
|
|
|
@ -1,18 +1,24 @@
|
|||
package org.eclipse.jetty.servlets;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.security.DigestOutputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import org.eclipse.jetty.http.gzip.CompressionType;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.DefaultServlet;
|
||||
|
@ -25,21 +31,46 @@ import org.eclipse.jetty.toolchain.test.IO;
|
|||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
/**
|
||||
* Test the effects of Gzip filtering when in the context of HTTP/1.1 Pipelining.
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class GzipWithPipeliningTest
|
||||
{
|
||||
@Parameters
|
||||
public static Collection<String[]> data()
|
||||
{
|
||||
// Test different Content-Encoding header combinations. So implicitly testing that gzip is preferred oder deflate
|
||||
String[][] data = new String[][]
|
||||
{
|
||||
{ CompressionType.GZIP.getEncodingHeader() },
|
||||
{ CompressionType.DEFLATE.getEncodingHeader() + ", " + CompressionType.GZIP.getEncodingHeader() },
|
||||
{ CompressionType.GZIP.getEncodingHeader() + ", " + CompressionType.DEFLATE.getEncodingHeader() },
|
||||
{ CompressionType.DEFLATE.getEncodingHeader() }
|
||||
};
|
||||
|
||||
return Arrays.asList(data);
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestingDir testingdir = new TestingDir();
|
||||
|
||||
private Server server;
|
||||
private URI serverUri;
|
||||
private String encodingHeader;
|
||||
|
||||
|
||||
public GzipWithPipeliningTest(String encodingHeader)
|
||||
{
|
||||
this.encodingHeader = encodingHeader;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void startServer() throws Exception
|
||||
|
@ -86,7 +117,7 @@ public class GzipWithPipeliningTest
|
|||
testingdir.ensureEmpty();
|
||||
File outputDir = testingdir.getDir();
|
||||
|
||||
PipelineHelper client = new PipelineHelper(serverUri);
|
||||
PipelineHelper client = new PipelineHelper(serverUri, encodingHeader);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -95,7 +126,7 @@ public class GzipWithPipeliningTest
|
|||
|
||||
// Size of content, as it exists on disk, without gzip compression.
|
||||
long rawsize = txtFile.length() + pngFile.length();
|
||||
Assert.assertThat("Ensure that we have sufficient file size to trigger chunking",rawsize,greaterThan(300000L));
|
||||
assertThat("Ensure that we have sufficient file size to trigger chunking",rawsize,greaterThan(300000L));
|
||||
|
||||
String respHeader;
|
||||
|
||||
|
@ -106,8 +137,9 @@ public class GzipWithPipeliningTest
|
|||
|
||||
respHeader = client.readResponseHeader();
|
||||
System.out.println("Response Header #1 --\n" + respHeader);
|
||||
Assert.assertThat("Content-Encoding should be gzipped",respHeader,containsString("Content-Encoding: gzip\r\n"));
|
||||
Assert.assertThat("Transfer-Encoding should be chunked",respHeader,containsString("Transfer-Encoding: chunked\r\n"));
|
||||
String expectedEncodingHeader = encodingHeader.equals(CompressionType.DEFLATE.getEncodingHeader()) ? CompressionType.DEFLATE.getEncodingHeader() : CompressionType.GZIP.getEncodingHeader();
|
||||
assertThat("Content-Encoding should be gzipped",respHeader,containsString("Content-Encoding: " + expectedEncodingHeader + "\r\n"));
|
||||
assertThat("Transfer-Encoding should be chunked",respHeader,containsString("Transfer-Encoding: chunked\r\n"));
|
||||
|
||||
// Raw output / gzipped, writted to disk (checked for sha1sum later)
|
||||
File rawOutputFile = new File(outputDir, "response-1.gz");
|
||||
|
@ -118,7 +150,7 @@ public class GzipWithPipeliningTest
|
|||
|
||||
// Read only 20% - intentionally a partial read.
|
||||
System.out.println("Attempting to read partial content ...");
|
||||
int readBytes = client.readBody(rawOutputStream,(int)((float)chunkSize * 0.20f));
|
||||
int readBytes = client.readBody(rawOutputStream,(int)(chunkSize * 0.20f));
|
||||
System.out.printf("Read %,d bytes%n",readBytes);
|
||||
|
||||
// Issue another request
|
||||
|
@ -133,14 +165,14 @@ public class GzipWithPipeliningTest
|
|||
readBytes = client.readBody(rawOutputStream,(int)chunkSize);
|
||||
System.out.printf("Read %,d bytes%n",readBytes);
|
||||
line = client.readLine();
|
||||
Assert.assertThat("Chunk delim should be an empty line with CR+LF",line,is(""));
|
||||
assertThat("Chunk delim should be an empty line with CR+LF",line,is(""));
|
||||
chunkSize = client.readChunkSize();
|
||||
System.out.printf("Next Chunk: (0x%X) %,d bytes%n",chunkSize,chunkSize);
|
||||
}
|
||||
|
||||
// Inter-pipeline delim
|
||||
line = client.readLine();
|
||||
Assert.assertThat("Inter-pipeline delim should be an empty line with CR+LF",line,is(""));
|
||||
assertThat("Inter-pipeline delim should be an empty line with CR+LF",line,is(""));
|
||||
|
||||
// Sha1tracking for 1st Request
|
||||
MessageDigest digestTxt = MessageDigest.getInstance("SHA1");
|
||||
|
@ -149,14 +181,23 @@ public class GzipWithPipeliningTest
|
|||
// Decompress 1st request and calculate sha1sum
|
||||
IO.close(rawOutputStream);
|
||||
FileInputStream rawInputStream = new FileInputStream(rawOutputFile);
|
||||
GZIPInputStream ungzipStream = new GZIPInputStream(rawInputStream);
|
||||
IO.copy(ungzipStream, digesterTxt);
|
||||
InputStream uncompressedStream = null;
|
||||
if (CompressionType.DEFLATE.getEncodingHeader().equals(encodingHeader))
|
||||
{
|
||||
uncompressedStream = new InflaterInputStream(rawInputStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
uncompressedStream = new GZIPInputStream(rawInputStream);
|
||||
}
|
||||
|
||||
IO.copy(uncompressedStream, digesterTxt);
|
||||
|
||||
// Read 2nd request http response header
|
||||
respHeader = client.readResponseHeader();
|
||||
System.out.println("Response Header #2 --\n" + respHeader);
|
||||
Assert.assertThat("Content-Encoding should NOT be gzipped",respHeader,not(containsString("Content-Encoding: gzip\r\n")));
|
||||
Assert.assertThat("Transfer-Encoding should NOT be chunked",respHeader,not(containsString("Transfer-Encoding: chunked\r\n")));
|
||||
assertThat("Content-Encoding should NOT be gzipped",respHeader,not(containsString("Content-Encoding: gzip\r\n")));
|
||||
assertThat("Transfer-Encoding should NOT be chunked",respHeader,not(containsString("Transfer-Encoding: chunked\r\n")));
|
||||
|
||||
// Sha1tracking for 2nd Request
|
||||
MessageDigest digestImg = MessageDigest.getInstance("SHA1");
|
||||
|
@ -164,7 +205,7 @@ public class GzipWithPipeliningTest
|
|||
|
||||
// Read 2nd request body
|
||||
int contentLength = client.getContentLength(respHeader);
|
||||
Assert.assertThat("Image Content Length",(long)contentLength,is(pngFile.length()));
|
||||
assertThat("Image Content Length",(long)contentLength,is(pngFile.length()));
|
||||
client.readBody(digesterImg,contentLength);
|
||||
|
||||
// Validate checksums
|
||||
|
@ -183,7 +224,7 @@ public class GzipWithPipeliningTest
|
|||
{
|
||||
String expectedSha1 = loadSha1sum(testResourceFile + ".sha1");
|
||||
String actualSha1 = Hex.asHex(digest.digest());
|
||||
Assert.assertEquals(testResourceFile + " / SHA1Sum of content",expectedSha1,actualSha1);
|
||||
assertEquals(testResourceFile + " / SHA1Sum of content",expectedSha1,actualSha1);
|
||||
}
|
||||
|
||||
private String loadSha1sum(String testResourceSha1Sum) throws IOException
|
||||
|
@ -192,7 +233,7 @@ public class GzipWithPipeliningTest
|
|||
String contents = IO.readToString(sha1File);
|
||||
Pattern pat = Pattern.compile("^[0-9A-Fa-f]*");
|
||||
Matcher mat = pat.matcher(contents);
|
||||
Assert.assertTrue("Should have found HEX code in SHA1 file: " + sha1File,mat.find());
|
||||
assertTrue("Should have found HEX code in SHA1 file: " + sha1File,mat.find());
|
||||
return mat.group();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,14 +13,21 @@
|
|||
|
||||
package org.eclipse.jetty.servlets;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.eclipse.jetty.http.gzip.CompressionType;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlets.gzip.GzipTester;
|
||||
import org.eclipse.jetty.servlets.gzip.TestMinGzipSizeServlet;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
/**
|
||||
* Perform specific tests on the IncludableGzipFilter's ability to manage
|
||||
|
@ -28,17 +35,36 @@ import org.junit.Test;
|
|||
*
|
||||
* @see <a href="Eclipse Bug 366106">http://bugs.eclipse.org/366106</a>
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class IncludableGzipFilterMinSizeTest
|
||||
{
|
||||
@Parameters
|
||||
public static Collection<CompressionType[]> data()
|
||||
{
|
||||
CompressionType[][] data = new CompressionType[][]
|
||||
{
|
||||
{ CompressionType.GZIP },
|
||||
{ CompressionType.DEFLATE }
|
||||
};
|
||||
|
||||
return Arrays.asList(data);
|
||||
}
|
||||
|
||||
public IncludableGzipFilterMinSizeTest(CompressionType compressionType)
|
||||
{
|
||||
this.compressionType = compressionType;
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestingDir testdir = new TestingDir();
|
||||
|
||||
private CompressionType compressionType;
|
||||
private Class<? extends Servlet> testServlet = TestMinGzipSizeServlet.class;
|
||||
|
||||
@Test
|
||||
public void testUnderMinSize() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testdir);
|
||||
GzipTester tester = new GzipTester(testdir, compressionType);
|
||||
// Use IncludableGzipFilter
|
||||
tester.setGzipFilterClass(IncludableGzipFilter.class);
|
||||
|
||||
|
@ -64,7 +90,7 @@ public class IncludableGzipFilterMinSizeTest
|
|||
@Test
|
||||
public void testOverMinSize() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testdir);
|
||||
GzipTester tester = new GzipTester(testdir, compressionType);
|
||||
// Use IncludableGzipFilter
|
||||
tester.setGzipFilterClass(IncludableGzipFilter.class);
|
||||
|
||||
|
|
|
@ -22,10 +22,14 @@ import java.io.ByteArrayOutputStream;
|
|||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.gzip.CompressionType;
|
||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.testing.HttpTester;
|
||||
|
@ -36,9 +40,28 @@ import org.junit.After;
|
|||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class IncludableGzipFilterTest
|
||||
{
|
||||
@Parameters
|
||||
public static Collection<CompressionType[]> data()
|
||||
{
|
||||
CompressionType[][] data = new CompressionType[][]
|
||||
{
|
||||
{ CompressionType.GZIP },
|
||||
{ CompressionType.DEFLATE }
|
||||
};
|
||||
|
||||
return Arrays.asList(data);
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestingDir testdir = new TestingDir();
|
||||
|
||||
private static String __content =
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "+
|
||||
"Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "+
|
||||
|
@ -53,11 +76,14 @@ public class IncludableGzipFilterTest
|
|||
"Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+
|
||||
"et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
|
||||
|
||||
@Rule
|
||||
public TestingDir testdir = new TestingDir();
|
||||
|
||||
private ServletTester tester;
|
||||
|
||||
private CompressionType compressionType;
|
||||
|
||||
public IncludableGzipFilterTest(CompressionType compressionType)
|
||||
{
|
||||
this.compressionType = compressionType;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
|
@ -95,7 +121,7 @@ public class IncludableGzipFilterTest
|
|||
request.setMethod("GET");
|
||||
request.setVersion("HTTP/1.0");
|
||||
request.setHeader("Host","tester");
|
||||
request.setHeader("accept-encoding","gzip");
|
||||
request.setHeader("accept-encoding", compressionType.getEncodingHeader());
|
||||
request.setURI("/context/file.txt");
|
||||
|
||||
ByteArrayBuffer reqsBuff = new ByteArrayBuffer(request.generate().getBytes());
|
||||
|
@ -103,10 +129,19 @@ public class IncludableGzipFilterTest
|
|||
response.parse(respBuff.asArray());
|
||||
|
||||
assertTrue(response.getMethod()==null);
|
||||
assertTrue(response.getHeader("Content-Encoding").equalsIgnoreCase("gzip"));
|
||||
assertTrue(response.getHeader("Content-Encoding").equalsIgnoreCase(compressionType.getEncodingHeader()));
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
|
||||
InputStream testIn = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes()));
|
||||
InputStream testIn = null;
|
||||
ByteArrayInputStream compressedResponseStream = new ByteArrayInputStream(response.getContentBytes());
|
||||
if (compressionType.equals(CompressionType.GZIP))
|
||||
{
|
||||
testIn = new GZIPInputStream(compressedResponseStream);
|
||||
}
|
||||
else if (compressionType.equals(CompressionType.DEFLATE))
|
||||
{
|
||||
testIn = new InflaterInputStream(compressedResponseStream);
|
||||
}
|
||||
ByteArrayOutputStream testOut = new ByteArrayOutputStream();
|
||||
IO.copy(testIn,testOut);
|
||||
|
||||
|
|
|
@ -25,8 +25,9 @@ public class PipelineHelper
|
|||
private Socket socket;
|
||||
private OutputStream outputStream;
|
||||
private InputStream inputStream;
|
||||
private String encodingHeader;
|
||||
|
||||
public PipelineHelper(URI uri)
|
||||
public PipelineHelper(URI uri, String encodingHeader)
|
||||
{
|
||||
if (LOG instanceof StdErrLog)
|
||||
{
|
||||
|
@ -34,6 +35,7 @@ public class PipelineHelper
|
|||
}
|
||||
this.uri = uri;
|
||||
this.endpoint = new InetSocketAddress(uri.getHost(),uri.getPort());
|
||||
this.encodingHeader = encodingHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -76,7 +78,7 @@ public class PipelineHelper
|
|||
req.append("Accept-Language: en-us\r\n");
|
||||
if (acceptGzipped)
|
||||
{
|
||||
req.append("Accept-Encoding: gzip, deflate\r\n");
|
||||
req.append("Accept-Encoding: " + encodingHeader + "\r\n");
|
||||
}
|
||||
req.append("Cookie: JSESSIONID=spqx8v8szylt1336t96vc6mw0\r\n");
|
||||
if ( close )
|
||||
|
@ -134,7 +136,7 @@ public class PipelineHelper
|
|||
while (!(foundCR && foundLF))
|
||||
{
|
||||
b = inputStream.read();
|
||||
Assert.assertThat("Should not have hit EOL (yet) during chunk size read",(int)b,not(-1));
|
||||
Assert.assertThat("Should not have hit EOL (yet) during chunk size read",b,not(-1));
|
||||
if (b == 0x0D)
|
||||
{
|
||||
foundCR = true;
|
||||
|
@ -163,7 +165,7 @@ public class PipelineHelper
|
|||
while (!(foundCR && foundLF))
|
||||
{
|
||||
b = inputStream.read();
|
||||
Assert.assertThat("Should not have hit EOL (yet) during chunk size read",(int)b,not(-1));
|
||||
Assert.assertThat("Should not have hit EOL (yet) during chunk size read",b,not(-1));
|
||||
if (b == 0x0D)
|
||||
{
|
||||
foundCR = true;
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
package org.eclipse.jetty.servlets.gzip;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
|
@ -12,9 +20,12 @@ import java.util.Enumeration;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.gzip.CompressionType;
|
||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
|
@ -26,12 +37,6 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
|||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.junit.Assert;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
public class GzipTester
|
||||
{
|
||||
private Class<? extends GzipFilter> gzipFilterClass = GzipFilter.class;
|
||||
|
@ -39,10 +44,12 @@ public class GzipTester
|
|||
private String userAgent = null;
|
||||
private ServletTester servletTester;
|
||||
private TestingDir testdir;
|
||||
private CompressionType compressionType;
|
||||
|
||||
public GzipTester(TestingDir testingdir)
|
||||
public GzipTester(TestingDir testingdir, CompressionType compressionType)
|
||||
{
|
||||
this.testdir = testingdir;
|
||||
this.compressionType = compressionType;
|
||||
// Make sure we start with a clean testing directory.
|
||||
// DOES NOT WORK IN WINDOWS - this.testdir.ensureEmpty();
|
||||
}
|
||||
|
@ -61,7 +68,7 @@ public class GzipTester
|
|||
request.setMethod("GET");
|
||||
request.setVersion("HTTP/1.0");
|
||||
request.setHeader("Host","tester");
|
||||
request.setHeader("Accept-Encoding","gzip");
|
||||
request.setHeader("Accept-Encoding",compressionType.getEncodingHeader());
|
||||
if (this.userAgent != null)
|
||||
request.setHeader("User-Agent", this.userAgent);
|
||||
request.setURI("/context/" + requestedFilename);
|
||||
|
@ -76,7 +83,7 @@ public class GzipTester
|
|||
Assert.assertThat("Response.method",response.getMethod(),nullValue());
|
||||
Assert.assertThat("Response.status",response.getStatus(),is(HttpServletResponse.SC_OK));
|
||||
Assert.assertThat("Response.header[Content-Length]",response.getHeader("Content-Length"),notNullValue());
|
||||
Assert.assertThat("Response.header[Content-Encoding]",response.getHeader("Content-Encoding"),containsString("gzip"));
|
||||
Assert.assertThat("Response.header[Content-Encoding]",response.getHeader("Content-Encoding"),containsString(compressionType.getEncodingHeader()));
|
||||
|
||||
// Assert that the decompressed contents are what we expect.
|
||||
File serverFile = testdir.getFile(serverFilename);
|
||||
|
@ -89,12 +96,19 @@ public class GzipTester
|
|||
try
|
||||
{
|
||||
bais = new ByteArrayInputStream(response.getContentBytes());
|
||||
in = new GZIPInputStream(bais);
|
||||
if (compressionType.equals(CompressionType.GZIP))
|
||||
{
|
||||
in = new GZIPInputStream(bais);
|
||||
}
|
||||
else if (compressionType.equals(CompressionType.DEFLATE))
|
||||
{
|
||||
in = new InflaterInputStream(bais);
|
||||
}
|
||||
out = new ByteArrayOutputStream();
|
||||
IO.copy(in,out);
|
||||
|
||||
actual = out.toString(encoding);
|
||||
Assert.assertEquals("Uncompressed contents",expected,actual);
|
||||
assertThat("Uncompressed contents",actual,equalTo(expected));
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -128,7 +142,7 @@ public class GzipTester
|
|||
request.setMethod("GET");
|
||||
request.setVersion("HTTP/1.0");
|
||||
request.setHeader("Host","tester");
|
||||
request.setHeader("Accept-Encoding","gzip");
|
||||
request.setHeader("Accept-Encoding",compressionType.getEncodingHeader());
|
||||
if (this.userAgent != null)
|
||||
request.setHeader("User-Agent", this.userAgent);
|
||||
request.setURI("/context/" + requestedFilename);
|
||||
|
@ -215,7 +229,7 @@ public class GzipTester
|
|||
request.setMethod("GET");
|
||||
request.setVersion("HTTP/1.0");
|
||||
request.setHeader("Host","tester");
|
||||
request.setHeader("Accept-Encoding","gzip");
|
||||
request.setHeader("Accept-Encoding",compressionType.getEncodingHeader());
|
||||
if (this.userAgent != null)
|
||||
request.setHeader("User-Agent", this.userAgent);
|
||||
if (filename == null)
|
||||
|
@ -238,7 +252,7 @@ public class GzipTester
|
|||
int serverLength = Integer.parseInt(response.getHeader("Content-Length"));
|
||||
Assert.assertThat("Response.header[Content-Length]",serverLength,is(expectedFilesize));
|
||||
}
|
||||
Assert.assertThat("Response.header[Content-Encoding]",response.getHeader("Content-Encoding"),not(containsString("gzip")));
|
||||
Assert.assertThat("Response.header[Content-Encoding]",response.getHeader("Content-Encoding"),not(containsString(compressionType.getEncodingHeader())));
|
||||
|
||||
// Assert that the contents are what we expect.
|
||||
if (filename != null)
|
||||
|
|
Loading…
Reference in New Issue