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:
Michael Gorovoy 2011-06-20 20:55:58 +00:00
parent 1f790a5f78
commit f95e1bddbe
4 changed files with 1362 additions and 5 deletions

View File

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

View File

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

View File

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

View File

@ -48,7 +48,7 @@ import static org.junit.Assert.assertTrue;
public class GzipFilterTest
{
private static String _content =
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. "+
@ -74,7 +74,7 @@ public class GzipFilterTest
File testFile = testdir.getFile("file.txt");
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);
testOut.close();
@ -115,12 +115,10 @@ public class GzipFilterTest
assertTrue(response.getHeader("Content-Encoding").equalsIgnoreCase("gzip"));
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
int length = Integer.valueOf(response.getHeader("Content-Length"));
InputStream testIn = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes()));
ByteArrayOutputStream testOut = new ByteArrayOutputStream();
IO.copy(testIn,testOut);
assertEquals(_content, testOut.toString("UTF8"));
assertEquals(__content, testOut.toString("ISO8859_1"));
}
}