302566 GZIP handler implementation and unit test
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@3403 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
parent
1f790a5f78
commit
f95e1bddbe
|
@ -0,0 +1,699 @@
|
||||||
|
// ========================================================================
|
||||||
|
// 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.server.handler;
|
||||||
|
|
||||||
|
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;
|
||||||
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletOutputStream;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletResponseWrapper;
|
||||||
|
|
||||||
|
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.server.Request;
|
||||||
|
import org.eclipse.jetty.util.ByteArrayOutputStream2;
|
||||||
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* GZIP Handler This handler will gzip the content of a response if:
|
||||||
|
* <ul>
|
||||||
|
* <li>The filter is mapped to a matching path</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 if no mimeTypes are defined the
|
||||||
|
* content-type is not "application/gzip"</li>
|
||||||
|
* <li>No content-encoding is specified by the resource</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Compressing the content can greatly improve the network bandwidth usage, but at a cost of memory and CPU cycles. If this handler is used 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>
|
||||||
|
*/
|
||||||
|
public class GzipHandler extends HandlerWrapper
|
||||||
|
{
|
||||||
|
protected Set<String> _mimeTypes;
|
||||||
|
protected Set<String> _excluded;
|
||||||
|
protected int _bufferSize = 8192;
|
||||||
|
protected int _minGzipSize = 256;
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public GzipHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Get the mime types.
|
||||||
|
*
|
||||||
|
* @return mime types to set
|
||||||
|
*/
|
||||||
|
public Set<String> getMimeTypes()
|
||||||
|
{
|
||||||
|
return _mimeTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Set the mime types.
|
||||||
|
*
|
||||||
|
* @param mimeTypes
|
||||||
|
* the mime types to set
|
||||||
|
*/
|
||||||
|
public void setMimeTypes(Set<String> mimeTypes)
|
||||||
|
{
|
||||||
|
_mimeTypes = mimeTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Set the mime types.
|
||||||
|
*
|
||||||
|
* @param mimeTypes
|
||||||
|
* the mime types to set
|
||||||
|
*/
|
||||||
|
public void setMimeTypes(String mimeTypes)
|
||||||
|
{
|
||||||
|
if (mimeTypes != null)
|
||||||
|
{
|
||||||
|
_mimeTypes = new HashSet<String>();
|
||||||
|
StringTokenizer tok = new StringTokenizer(mimeTypes,",",false);
|
||||||
|
while (tok.hasMoreTokens())
|
||||||
|
{
|
||||||
|
_mimeTypes.add(tok.nextToken());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Get the excluded user agents.
|
||||||
|
*
|
||||||
|
* @return excluded user agents
|
||||||
|
*/
|
||||||
|
public Set<String> getExcluded()
|
||||||
|
{
|
||||||
|
return _excluded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Set the excluded user agents.
|
||||||
|
*
|
||||||
|
* @param excluded
|
||||||
|
* excluded user agents to set
|
||||||
|
*/
|
||||||
|
public void setExcluded(Set<String> excluded)
|
||||||
|
{
|
||||||
|
_excluded = excluded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Set the excluded user agents.
|
||||||
|
*
|
||||||
|
* @param excluded
|
||||||
|
* excluded user agents to set
|
||||||
|
*/
|
||||||
|
public void setExcluded(String excluded)
|
||||||
|
{
|
||||||
|
if (excluded != null)
|
||||||
|
{
|
||||||
|
_excluded = new HashSet<String>();
|
||||||
|
StringTokenizer tok = new StringTokenizer(excluded,",",false);
|
||||||
|
while (tok.hasMoreTokens())
|
||||||
|
_excluded.add(tok.nextToken());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Get the buffer size.
|
||||||
|
*
|
||||||
|
* @return the buffer size
|
||||||
|
*/
|
||||||
|
public int setBufferSize()
|
||||||
|
{
|
||||||
|
return _bufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Set the buffer size.
|
||||||
|
*
|
||||||
|
* @param bufferSize
|
||||||
|
* buffer size to set
|
||||||
|
*/
|
||||||
|
public void setBufferSize(int bufferSize)
|
||||||
|
{
|
||||||
|
_bufferSize = bufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Get the minimum reponse size.
|
||||||
|
*
|
||||||
|
* @return minimum reponse size
|
||||||
|
*/
|
||||||
|
public int getMinGzipSize()
|
||||||
|
{
|
||||||
|
return _minGzipSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Set the minimum reponse size.
|
||||||
|
*
|
||||||
|
* @param minGzipSize
|
||||||
|
* minimum reponse size
|
||||||
|
*/
|
||||||
|
public void setMinGzipSize(int minGzipSize)
|
||||||
|
{
|
||||||
|
_minGzipSize = minGzipSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||||
|
{
|
||||||
|
if (_handler!=null && isStarted())
|
||||||
|
{
|
||||||
|
String ae = request.getHeader("accept-encoding");
|
||||||
|
if (ae != null && ae.indexOf("gzip")>=0 && !response.containsHeader("Content-Encoding")
|
||||||
|
&& !HttpMethods.HEAD.equalsIgnoreCase(request.getMethod()))
|
||||||
|
{
|
||||||
|
if (_excluded!=null)
|
||||||
|
{
|
||||||
|
String ua = request.getHeader("User-Agent");
|
||||||
|
if (_excluded.contains(ua))
|
||||||
|
{
|
||||||
|
_handler.handle(target,baseRequest, request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final GZIPResponseWrapper wrappedResponse = newGZIPResponseWrapper(request,response);
|
||||||
|
|
||||||
|
boolean exceptional=true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_handler.handle(target, baseRequest, request, wrappedResponse);
|
||||||
|
exceptional=false;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (exceptional && !response.isCommitted())
|
||||||
|
{
|
||||||
|
wrappedResponse.resetBuffer();
|
||||||
|
wrappedResponse.noGzip();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
wrappedResponse.finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_handler.handle(target,baseRequest, request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected GZIPResponseWrapper newGZIPResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||||
|
{
|
||||||
|
return new GZIPResponseWrapper(request,response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GZIPResponseWrapper extends HttpServletResponseWrapper
|
||||||
|
{
|
||||||
|
HttpServletRequest _request;
|
||||||
|
boolean _noGzip;
|
||||||
|
PrintWriter _writer;
|
||||||
|
GzipStream _gzStream;
|
||||||
|
long _contentLength = -1;
|
||||||
|
|
||||||
|
public GZIPResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||||
|
{
|
||||||
|
super(response);
|
||||||
|
_request = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
&& (_mimeTypes == null && "application/gzip".equalsIgnoreCase(ct) || _mimeTypes != null
|
||||||
|
&& (ct == null || !_mimeTypes.contains(StringUtil.asciiToLowerCase(ct)))))
|
||||||
|
{
|
||||||
|
noGzip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(int sc, String sm)
|
||||||
|
{
|
||||||
|
super.setStatus(sc,sm);
|
||||||
|
if (sc < 200 || sc >= 300)
|
||||||
|
noGzip();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(int sc)
|
||||||
|
{
|
||||||
|
super.setStatus(sc);
|
||||||
|
if (sc < 200 || sc >= 300)
|
||||||
|
noGzip();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentLength(int length)
|
||||||
|
{
|
||||||
|
_contentLength = length;
|
||||||
|
if (_gzStream != null)
|
||||||
|
_gzStream.setContentLength(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addHeader(String name, String value)
|
||||||
|
{
|
||||||
|
if ("content-length".equalsIgnoreCase(name))
|
||||||
|
{
|
||||||
|
_contentLength = Long.parseLong(value);
|
||||||
|
if (_gzStream != null)
|
||||||
|
_gzStream.setContentLength(_contentLength);
|
||||||
|
}
|
||||||
|
else if ("content-type".equalsIgnoreCase(name))
|
||||||
|
{
|
||||||
|
setContentType(value);
|
||||||
|
}
|
||||||
|
else if ("content-encoding".equalsIgnoreCase(name))
|
||||||
|
{
|
||||||
|
super.addHeader(name,value);
|
||||||
|
if (!isCommitted())
|
||||||
|
{
|
||||||
|
noGzip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
super.addHeader(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeader(String name, String value)
|
||||||
|
{
|
||||||
|
if ("content-length".equalsIgnoreCase(name))
|
||||||
|
{
|
||||||
|
_contentLength = Long.parseLong(value);
|
||||||
|
if (_gzStream != null)
|
||||||
|
_gzStream.setContentLength(_contentLength);
|
||||||
|
}
|
||||||
|
else if ("content-type".equalsIgnoreCase(name))
|
||||||
|
{
|
||||||
|
setContentType(value);
|
||||||
|
}
|
||||||
|
else if ("content-encoding".equalsIgnoreCase(name))
|
||||||
|
{
|
||||||
|
super.setHeader(name,value);
|
||||||
|
if (!isCommitted())
|
||||||
|
{
|
||||||
|
noGzip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
super.setHeader(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flushBuffer() throws IOException
|
||||||
|
{
|
||||||
|
if (_writer != null)
|
||||||
|
_writer.flush();
|
||||||
|
if (_gzStream != null)
|
||||||
|
_gzStream.finish();
|
||||||
|
else
|
||||||
|
getResponse().flushBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset()
|
||||||
|
{
|
||||||
|
super.reset();
|
||||||
|
if (_gzStream != null)
|
||||||
|
_gzStream.resetBuffer();
|
||||||
|
_writer = null;
|
||||||
|
_gzStream = null;
|
||||||
|
_noGzip = false;
|
||||||
|
_contentLength = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetBuffer()
|
||||||
|
{
|
||||||
|
super.resetBuffer();
|
||||||
|
if (_gzStream != null)
|
||||||
|
_gzStream.resetBuffer();
|
||||||
|
_writer = null;
|
||||||
|
_gzStream = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendError(int sc, String msg) throws IOException
|
||||||
|
{
|
||||||
|
resetBuffer();
|
||||||
|
super.sendError(sc,msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendError(int sc) throws IOException
|
||||||
|
{
|
||||||
|
resetBuffer();
|
||||||
|
super.sendError(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendRedirect(String location) throws IOException
|
||||||
|
{
|
||||||
|
resetBuffer();
|
||||||
|
super.sendRedirect(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServletOutputStream getOutputStream() throws IOException
|
||||||
|
{
|
||||||
|
if (_gzStream == null)
|
||||||
|
{
|
||||||
|
if (getResponse().isCommitted() || _noGzip)
|
||||||
|
return getResponse().getOutputStream();
|
||||||
|
|
||||||
|
_gzStream = newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize);
|
||||||
|
}
|
||||||
|
else if (_writer != null)
|
||||||
|
throw new IllegalStateException("getWriter() called");
|
||||||
|
|
||||||
|
return _gzStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PrintWriter getWriter() throws IOException
|
||||||
|
{
|
||||||
|
if (_writer == null)
|
||||||
|
{
|
||||||
|
if (_gzStream != null)
|
||||||
|
throw new IllegalStateException("getOutputStream() called");
|
||||||
|
|
||||||
|
if (getResponse().isCommitted() || _noGzip)
|
||||||
|
return getResponse().getWriter();
|
||||||
|
|
||||||
|
_gzStream = newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize);
|
||||||
|
_writer = newWriter(_gzStream,getCharacterEncoding());
|
||||||
|
}
|
||||||
|
return _writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void noGzip()
|
||||||
|
{
|
||||||
|
_noGzip = true;
|
||||||
|
if (_gzStream != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_gzStream.doNotGzip();
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void finish() throws IOException
|
||||||
|
{
|
||||||
|
if (_writer != null && !_gzStream._closed)
|
||||||
|
_writer.flush();
|
||||||
|
if (_gzStream != null)
|
||||||
|
_gzStream.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected GzipStream newGzipStream(HttpServletRequest request, HttpServletResponse response, long contentLength, int bufferSize, int minGzipSize)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
return new GzipStream(request,response,contentLength,bufferSize,minGzipSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static 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;
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContentLength(long length)
|
||||||
|
{
|
||||||
|
_contentLength = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flush() throws IOException
|
||||||
|
{
|
||||||
|
if (_out == null || _bOut != null)
|
||||||
|
{
|
||||||
|
if (_contentLength > 0 && _contentLength < _minGzipSize)
|
||||||
|
doNotGzip();
|
||||||
|
else
|
||||||
|
doGzip();
|
||||||
|
}
|
||||||
|
|
||||||
|
_out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(int b) throws IOException
|
||||||
|
{
|
||||||
|
checkOut(1);
|
||||||
|
_out.write(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte b[]) throws IOException
|
||||||
|
{
|
||||||
|
checkOut(b.length);
|
||||||
|
_out.write(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(byte b[], int off, int len) throws IOException
|
||||||
|
{
|
||||||
|
checkOut(len);
|
||||||
|
_out.write(b,off,len);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean setContentEncodingGzip()
|
||||||
|
{
|
||||||
|
_response.setHeader("Content-Encoding","gzip");
|
||||||
|
return _response.containsHeader("Content-Encoding");
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void doNotGzip() throws IOException
|
||||||
|
{
|
||||||
|
if (_gzOut != null)
|
||||||
|
throw new IllegalStateException();
|
||||||
|
if (_out == null || _bOut != null)
|
||||||
|
{
|
||||||
|
_out = _response.getOutputStream();
|
||||||
|
if (_contentLength >= 0)
|
||||||
|
{
|
||||||
|
if (_contentLength < Integer.MAX_VALUE)
|
||||||
|
_response.setContentLength((int)_contentLength);
|
||||||
|
else
|
||||||
|
_response.setHeader("Content-Length",Long.toString(_contentLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_bOut != null)
|
||||||
|
_out.write(_bOut.getBuf(),0,_bOut.getCount());
|
||||||
|
_bOut = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 2004-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.server.handler;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||||
|
import org.eclipse.jetty.server.Handler;
|
||||||
|
import org.eclipse.jetty.server.LocalConnector;
|
||||||
|
import org.eclipse.jetty.server.Request;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.util.IO;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class GzipHandlerTest
|
||||||
|
{
|
||||||
|
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 "+
|
||||||
|
"habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "+
|
||||||
|
"Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam "+
|
||||||
|
"at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate "+
|
||||||
|
"velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. "+
|
||||||
|
"Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum "+
|
||||||
|
"eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa "+
|
||||||
|
"sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam "+
|
||||||
|
"consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. "+
|
||||||
|
"Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+
|
||||||
|
"et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
|
||||||
|
|
||||||
|
private Server _server;
|
||||||
|
private LocalConnector _connector;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init() throws Exception
|
||||||
|
{
|
||||||
|
_server = new Server();
|
||||||
|
|
||||||
|
_connector = new LocalConnector();
|
||||||
|
_server.addConnector(_connector);
|
||||||
|
|
||||||
|
Handler testHandler = new AbstractHandler()
|
||||||
|
{
|
||||||
|
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException,
|
||||||
|
ServletException
|
||||||
|
{
|
||||||
|
PrintWriter writer = response.getWriter();
|
||||||
|
writer.write(__content);
|
||||||
|
writer.close();
|
||||||
|
|
||||||
|
baseRequest.setHandled(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
GzipHandler gzipHandler = new GzipHandler();
|
||||||
|
gzipHandler.setHandler(testHandler);
|
||||||
|
|
||||||
|
_server.setHandler(gzipHandler);
|
||||||
|
_server.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void destroy() throws Exception
|
||||||
|
{
|
||||||
|
_server.stop();
|
||||||
|
_server.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGzipHandler() throws Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
// generated and parsed test
|
||||||
|
HttpTester request = new HttpTester();
|
||||||
|
HttpTester response = new HttpTester();
|
||||||
|
|
||||||
|
request.setMethod("GET");
|
||||||
|
request.setVersion("HTTP/1.0");
|
||||||
|
request.setHeader("Host","tester");
|
||||||
|
request.setHeader("accept-encoding","gzip");
|
||||||
|
request.setURI("/");
|
||||||
|
|
||||||
|
ByteArrayBuffer reqsBuff = new ByteArrayBuffer(request.generate().getBytes());
|
||||||
|
ByteArrayBuffer respBuff = _connector.getResponses(reqsBuff, false);
|
||||||
|
response.parse(respBuff.asArray());
|
||||||
|
|
||||||
|
assertTrue(response.getMethod()==null);
|
||||||
|
assertTrue(response.getHeader("Content-Encoding").equalsIgnoreCase("gzip"));
|
||||||
|
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||||
|
|
||||||
|
InputStream testIn = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes()));
|
||||||
|
ByteArrayOutputStream testOut = new ByteArrayOutputStream();
|
||||||
|
IO.copy(testIn,testOut);
|
||||||
|
|
||||||
|
assertEquals(__content, testOut.toString("UTF8"));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,537 @@
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 2004-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.server.handler;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
|
||||||
|
import javax.servlet.http.Cookie;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.HttpFields;
|
||||||
|
import org.eclipse.jetty.http.HttpGenerator;
|
||||||
|
import org.eclipse.jetty.http.HttpHeaders;
|
||||||
|
import org.eclipse.jetty.http.HttpParser;
|
||||||
|
import org.eclipse.jetty.http.HttpVersions;
|
||||||
|
import org.eclipse.jetty.http.MimeTypes;
|
||||||
|
import org.eclipse.jetty.io.Buffer;
|
||||||
|
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||||
|
import org.eclipse.jetty.io.SimpleBuffers;
|
||||||
|
import org.eclipse.jetty.io.View;
|
||||||
|
import org.eclipse.jetty.io.bio.StringEndPoint;
|
||||||
|
import org.eclipse.jetty.util.ByteArrayOutputStream2;
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/** Test support class.
|
||||||
|
* Assist with parsing and generating HTTP requests and responses.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* HttpTester tester = new HttpTester();
|
||||||
|
*
|
||||||
|
* tester.parse(
|
||||||
|
* "GET /uri HTTP/1.1\r\n"+
|
||||||
|
* "Host: fakehost\r\n"+
|
||||||
|
* "Content-Length: 10\r\n" +
|
||||||
|
* "\r\n");
|
||||||
|
*
|
||||||
|
* System.err.println(tester.getMethod());
|
||||||
|
* System.err.println(tester.getURI());
|
||||||
|
* System.err.println(tester.getVersion());
|
||||||
|
* System.err.println(tester.getHeader("Host"));
|
||||||
|
* System.err.println(tester.getContent());
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @see org.eclipse.jetty.testing.ServletTester
|
||||||
|
*/
|
||||||
|
public class HttpTester
|
||||||
|
{
|
||||||
|
protected HttpFields _fields=new HttpFields();
|
||||||
|
protected String _method;
|
||||||
|
protected String _uri;
|
||||||
|
protected String _version;
|
||||||
|
protected int _status;
|
||||||
|
protected String _reason;
|
||||||
|
protected ByteArrayOutputStream2 _parsedContent;
|
||||||
|
protected byte[] _genContent;
|
||||||
|
|
||||||
|
private String _charset, _defaultCharset;
|
||||||
|
private Buffer _contentType;
|
||||||
|
|
||||||
|
public HttpTester()
|
||||||
|
{
|
||||||
|
this("UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpTester(String charset)
|
||||||
|
{
|
||||||
|
_defaultCharset = charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset()
|
||||||
|
{
|
||||||
|
_fields.clear();
|
||||||
|
_method=null;
|
||||||
|
_uri=null;
|
||||||
|
_version=null;
|
||||||
|
_status=0;
|
||||||
|
_reason=null;
|
||||||
|
_parsedContent=null;
|
||||||
|
_genContent=null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getString(Buffer buffer)
|
||||||
|
{
|
||||||
|
return getString(buffer.asArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getString(byte[] b)
|
||||||
|
{
|
||||||
|
if(_charset==null)
|
||||||
|
return new String(b);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new String(b, _charset);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
return new String(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] getByteArray(String str)
|
||||||
|
{
|
||||||
|
if(_charset==null)
|
||||||
|
return str.getBytes();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return str.getBytes(_charset);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
return str.getBytes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Parse one HTTP request or response
|
||||||
|
* @param rawHTTP Raw HTTP to parse
|
||||||
|
* @return Any unparsed data in the rawHTTP (eg pipelined requests)
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public String parse(String rawHTTP) throws IOException
|
||||||
|
{
|
||||||
|
_charset = _defaultCharset;
|
||||||
|
ByteArrayBuffer buf = new ByteArrayBuffer(getByteArray(rawHTTP));
|
||||||
|
View view = new View(buf);
|
||||||
|
HttpParser parser = new HttpParser(view,new PH());
|
||||||
|
parser.parse();
|
||||||
|
return getString(view.asArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* Parse one HTTP request or response
|
||||||
|
* @param rawHTTP Raw HTTP to parse
|
||||||
|
* @return Any unparsed data in the rawHTTP (eg pipelined requests)
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public byte[] parse(byte[] rawHTTP) throws IOException
|
||||||
|
{
|
||||||
|
_charset = _defaultCharset;
|
||||||
|
ByteArrayBuffer buf = new ByteArrayBuffer(rawHTTP);
|
||||||
|
View view = new View(buf);
|
||||||
|
HttpParser parser = new HttpParser(view,new PH());
|
||||||
|
parser.parse();
|
||||||
|
return view.asArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public String generate() throws IOException
|
||||||
|
{
|
||||||
|
_charset = _defaultCharset;
|
||||||
|
_contentType = _fields.get(HttpHeaders.CONTENT_TYPE_BUFFER);
|
||||||
|
if(_contentType!=null)
|
||||||
|
{
|
||||||
|
String charset = MimeTypes.getCharsetFromContentType(_contentType);
|
||||||
|
if(charset!=null)
|
||||||
|
_charset = charset;
|
||||||
|
}
|
||||||
|
Buffer bb=new ByteArrayBuffer(32*1024 + (_genContent!=null?_genContent.length:0));
|
||||||
|
Buffer sb=new ByteArrayBuffer(4*1024);
|
||||||
|
StringEndPoint endp = new StringEndPoint(_charset);
|
||||||
|
HttpGenerator generator = new HttpGenerator(new SimpleBuffers(sb,bb),endp);
|
||||||
|
|
||||||
|
if (_method!=null)
|
||||||
|
{
|
||||||
|
generator.setRequest(getMethod(),getURI());
|
||||||
|
if (_version==null)
|
||||||
|
generator.setVersion(HttpVersions.HTTP_1_1_ORDINAL);
|
||||||
|
else
|
||||||
|
generator.setVersion(HttpVersions.CACHE.getOrdinal(HttpVersions.CACHE.lookup(_version)));
|
||||||
|
generator.completeHeader(_fields,false);
|
||||||
|
if (_genContent!=null)
|
||||||
|
generator.addContent(new View(new ByteArrayBuffer(_genContent)),false);
|
||||||
|
else if (_parsedContent!=null)
|
||||||
|
generator.addContent(new ByteArrayBuffer(_parsedContent.toByteArray()),false);
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.complete();
|
||||||
|
generator.flushBuffer();
|
||||||
|
return endp.getOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return the method
|
||||||
|
*/
|
||||||
|
public String getMethod()
|
||||||
|
{
|
||||||
|
return _method;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param method the method to set
|
||||||
|
*/
|
||||||
|
public void setMethod(String method)
|
||||||
|
{
|
||||||
|
_method=method;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return the reason
|
||||||
|
*/
|
||||||
|
public String getReason()
|
||||||
|
{
|
||||||
|
return _reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param reason the reason to set
|
||||||
|
*/
|
||||||
|
public void setReason(String reason)
|
||||||
|
{
|
||||||
|
_reason=reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return the status
|
||||||
|
*/
|
||||||
|
public int getStatus()
|
||||||
|
{
|
||||||
|
return _status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param status the status to set
|
||||||
|
*/
|
||||||
|
public void setStatus(int status)
|
||||||
|
{
|
||||||
|
_status=status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return the uri
|
||||||
|
*/
|
||||||
|
public String getURI()
|
||||||
|
{
|
||||||
|
return _uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param uri the uri to set
|
||||||
|
*/
|
||||||
|
public void setURI(String uri)
|
||||||
|
{
|
||||||
|
_uri=uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return the version
|
||||||
|
*/
|
||||||
|
public String getVersion()
|
||||||
|
{
|
||||||
|
return _version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param version the version to set
|
||||||
|
*/
|
||||||
|
public void setVersion(String version)
|
||||||
|
{
|
||||||
|
_version=version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public String getContentType()
|
||||||
|
{
|
||||||
|
return getString(_contentType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public String getCharacterEncoding()
|
||||||
|
{
|
||||||
|
return _charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @param value
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* @see org.eclipse.jetty.http.HttpFields#add(java.lang.String, java.lang.String)
|
||||||
|
*/
|
||||||
|
public void addHeader(String name, String value) throws IllegalArgumentException
|
||||||
|
{
|
||||||
|
_fields.add(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @param date
|
||||||
|
* @see org.eclipse.jetty.http.HttpFields#addDateField(java.lang.String, long)
|
||||||
|
*/
|
||||||
|
public void addDateHeader(String name, long date)
|
||||||
|
{
|
||||||
|
_fields.addDateField(name,date);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @param value
|
||||||
|
* @see org.eclipse.jetty.http.HttpFields#addLongField(java.lang.String, long)
|
||||||
|
*/
|
||||||
|
public void addLongHeader(String name, long value)
|
||||||
|
{
|
||||||
|
_fields.addLongField(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param cookie
|
||||||
|
* @see org.eclipse.jetty.http.HttpFields#addSetCookie(org.eclipse.jetty.http.HttpCookie)
|
||||||
|
*/
|
||||||
|
public void addSetCookie(Cookie cookie)
|
||||||
|
{
|
||||||
|
_fields.addSetCookie(
|
||||||
|
cookie.getName(),
|
||||||
|
cookie.getValue(),
|
||||||
|
cookie.getDomain(),
|
||||||
|
cookie.getPath(),
|
||||||
|
cookie.getMaxAge(),
|
||||||
|
cookie.getComment(),
|
||||||
|
cookie.getSecure(),
|
||||||
|
false,
|
||||||
|
cookie.getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @return the header value as a date
|
||||||
|
* @see org.eclipse.jetty.http.HttpFields#getDateField(java.lang.String)
|
||||||
|
*/
|
||||||
|
public long getDateHeader(String name)
|
||||||
|
{
|
||||||
|
return _fields.getDateField(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @return the header value names
|
||||||
|
* @see org.eclipse.jetty.http.HttpFields#getFieldNames()
|
||||||
|
*/
|
||||||
|
public Enumeration getHeaderNames()
|
||||||
|
{
|
||||||
|
return _fields.getFieldNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @return the header value as a long
|
||||||
|
* @throws NumberFormatException
|
||||||
|
* @see org.eclipse.jetty.http.HttpFields#getLongField(java.lang.String)
|
||||||
|
*/
|
||||||
|
public long getLongHeader(String name) throws NumberFormatException
|
||||||
|
{
|
||||||
|
return _fields.getLongField(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @return the header value
|
||||||
|
* @see org.eclipse.jetty.http.HttpFields#getStringField(java.lang.String)
|
||||||
|
*/
|
||||||
|
public String getHeader(String name)
|
||||||
|
{
|
||||||
|
return _fields.getStringField(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @return the header values
|
||||||
|
* @see org.eclipse.jetty.http.HttpFields#getValues(java.lang.String)
|
||||||
|
*/
|
||||||
|
public Enumeration getHeaderValues(String name)
|
||||||
|
{
|
||||||
|
return _fields.getValues(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @param value
|
||||||
|
* @see org.eclipse.jetty.http.HttpFields#put(java.lang.String, java.lang.String)
|
||||||
|
*/
|
||||||
|
public void setHeader(String name, String value)
|
||||||
|
{
|
||||||
|
_fields.put(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @param date
|
||||||
|
* @see org.eclipse.jetty.http.HttpFields#putDateField(java.lang.String, long)
|
||||||
|
*/
|
||||||
|
public void setDateHeader(String name, long date)
|
||||||
|
{
|
||||||
|
_fields.putDateField(name,date);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @param value
|
||||||
|
* @see org.eclipse.jetty.http.HttpFields#putLongField(java.lang.String, long)
|
||||||
|
*/
|
||||||
|
public void setLongHeader(String name, long value)
|
||||||
|
{
|
||||||
|
_fields.putLongField(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
* @param name
|
||||||
|
* @see org.eclipse.jetty.http.HttpFields#remove(java.lang.String)
|
||||||
|
*/
|
||||||
|
public void removeHeader(String name)
|
||||||
|
{
|
||||||
|
_fields.remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public String getContent()
|
||||||
|
{
|
||||||
|
if (_parsedContent!=null)
|
||||||
|
return getString(_parsedContent.toByteArray());
|
||||||
|
if (_genContent!=null)
|
||||||
|
return getString(_genContent);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public byte[] getContentBytes()
|
||||||
|
{
|
||||||
|
if (_parsedContent!=null)
|
||||||
|
return _parsedContent.toByteArray();
|
||||||
|
if (_genContent!=null)
|
||||||
|
return _genContent;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
public void setContent(String content)
|
||||||
|
{
|
||||||
|
_parsedContent=null;
|
||||||
|
if (content!=null)
|
||||||
|
{
|
||||||
|
_genContent=getByteArray(content);
|
||||||
|
setLongHeader(HttpHeaders.CONTENT_LENGTH,_genContent.length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
removeHeader(HttpHeaders.CONTENT_LENGTH);
|
||||||
|
_genContent=null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
private class PH extends HttpParser.EventHandler
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void startRequest(Buffer method, Buffer url, Buffer version) throws IOException
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
_method=getString(method);
|
||||||
|
_uri=getString(url);
|
||||||
|
_version=getString(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startResponse(Buffer version, int status, Buffer reason) throws IOException
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
_version=getString(version);
|
||||||
|
_status=status;
|
||||||
|
_reason=getString(reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void parsedHeader(Buffer name, Buffer value) throws IOException
|
||||||
|
{
|
||||||
|
_fields.add(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void headerComplete() throws IOException
|
||||||
|
{
|
||||||
|
_contentType = _fields.get(HttpHeaders.CONTENT_TYPE_BUFFER);
|
||||||
|
if(_contentType!=null)
|
||||||
|
{
|
||||||
|
String charset = MimeTypes.getCharsetFromContentType(_contentType);
|
||||||
|
if(charset!=null)
|
||||||
|
_charset = charset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void messageComplete(long contextLength) throws IOException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void content(Buffer ref) throws IOException
|
||||||
|
{
|
||||||
|
if (_parsedContent==null)
|
||||||
|
_parsedContent=new ByteArrayOutputStream2();
|
||||||
|
_parsedContent.write(ref.asArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -48,7 +48,7 @@ import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class GzipFilterTest
|
public class GzipFilterTest
|
||||||
{
|
{
|
||||||
private static String _content =
|
private static String __content =
|
||||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "+
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "+
|
||||||
"Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "+
|
"Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "+
|
||||||
"habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "+
|
"habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "+
|
||||||
|
@ -74,7 +74,7 @@ public class GzipFilterTest
|
||||||
|
|
||||||
File testFile = testdir.getFile("file.txt");
|
File testFile = testdir.getFile("file.txt");
|
||||||
BufferedOutputStream testOut = new BufferedOutputStream(new FileOutputStream(testFile));
|
BufferedOutputStream testOut = new BufferedOutputStream(new FileOutputStream(testFile));
|
||||||
ByteArrayInputStream testIn = new ByteArrayInputStream(_content.getBytes("ISO8859_1"));
|
ByteArrayInputStream testIn = new ByteArrayInputStream(__content.getBytes("ISO8859_1"));
|
||||||
IO.copy(testIn,testOut);
|
IO.copy(testIn,testOut);
|
||||||
testOut.close();
|
testOut.close();
|
||||||
|
|
||||||
|
@ -115,12 +115,10 @@ public class GzipFilterTest
|
||||||
assertTrue(response.getHeader("Content-Encoding").equalsIgnoreCase("gzip"));
|
assertTrue(response.getHeader("Content-Encoding").equalsIgnoreCase("gzip"));
|
||||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||||
|
|
||||||
int length = Integer.valueOf(response.getHeader("Content-Length"));
|
|
||||||
|
|
||||||
InputStream testIn = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes()));
|
InputStream testIn = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes()));
|
||||||
ByteArrayOutputStream testOut = new ByteArrayOutputStream();
|
ByteArrayOutputStream testOut = new ByteArrayOutputStream();
|
||||||
IO.copy(testIn,testOut);
|
IO.copy(testIn,testOut);
|
||||||
|
|
||||||
assertEquals(_content, testOut.toString("UTF8"));
|
assertEquals(__content, testOut.toString("ISO8859_1"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue