302566 GZIP handler for embedded Jetty servers
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@3406 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
parent
418ebe8268
commit
8c63ca989b
|
@ -1,5 +1,6 @@
|
|||
jetty-7.4.3-SNAPSHOT
|
||||
+ 295832 ProxyServlet more extensible and configurable
|
||||
+ 302566 GZIP handler for embedded Jetty servers
|
||||
+ 347617 Dynamically install/update/remove OSGi bundles discovered in the contexts folder
|
||||
+ 347717 start.jar destroys dependent child of --exec
|
||||
+ 347898 Close channel on JVM exceptions
|
||||
|
|
|
@ -48,5 +48,16 @@
|
|||
<artifactId>jetty-websocket</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>test-jetty-servlet</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.server.handler;
|
||||
package org.eclipse.jetty.embedded;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
@ -32,6 +32,9 @@ 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.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.server.handler.GzipHandler;
|
||||
import org.eclipse.jetty.testing.HttpTester;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
|
@ -17,6 +17,11 @@
|
|||
<artifactId>jetty-io</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
|
|
@ -0,0 +1,394 @@
|
|||
// ========================================================================
|
||||
// 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.Set;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
public class GzipResponseWrapper extends HttpServletResponseWrapper
|
||||
{
|
||||
private HttpServletRequest _request;
|
||||
private Set<String> _mimeTypes;
|
||||
private int _bufferSize=8192;
|
||||
private int _minGzipSize=256;
|
||||
|
||||
private PrintWriter _writer;
|
||||
private GzipStream _gzStream;
|
||||
private long _contentLength=-1;
|
||||
private boolean _noGzip;
|
||||
|
||||
/**
|
||||
* Instantiates a new gzip response wrapper.
|
||||
*
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
*/
|
||||
public GzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
super(response);
|
||||
_request=request;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Sets the mime types.
|
||||
*
|
||||
* @param mimeTypes the new mime types
|
||||
*/
|
||||
public void setMimeTypes(Set<String> mimeTypes)
|
||||
{
|
||||
_mimeTypes = mimeTypes;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#setBufferSize(int)
|
||||
*/
|
||||
public void setBufferSize(int bufferSize)
|
||||
{
|
||||
_bufferSize = bufferSize;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Sets the min gzip size.
|
||||
*
|
||||
* @param minGzipSize the new min gzip size
|
||||
*/
|
||||
public void setMinGzipSize(int minGzipSize)
|
||||
{
|
||||
_minGzipSize = minGzipSize;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#setContentType(java.lang.String)
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#setStatus(int, java.lang.String)
|
||||
*/
|
||||
public void setStatus(int sc, String sm)
|
||||
{
|
||||
super.setStatus(sc,sm);
|
||||
if (sc<200||sc>=300)
|
||||
noGzip();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#setStatus(int)
|
||||
*/
|
||||
public void setStatus(int sc)
|
||||
{
|
||||
super.setStatus(sc);
|
||||
if (sc<200||sc>=300)
|
||||
noGzip();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#setContentLength(int)
|
||||
*/
|
||||
public void setContentLength(int length)
|
||||
{
|
||||
_contentLength=length;
|
||||
if (_gzStream!=null)
|
||||
_gzStream.setContentLength(length);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#addHeader(java.lang.String, java.lang.String)
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServletResponseWrapper#setHeader(java.lang.String, java.lang.String)
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @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()
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.ServletResponseWrapper#getWriter()
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void finish() throws IOException
|
||||
{
|
||||
if (_writer!=null && !_gzStream._closed)
|
||||
_writer.flush();
|
||||
if (_gzStream!=null)
|
||||
_gzStream.finish();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param out the out
|
||||
* @param encoding the encoding
|
||||
* @return the prints the writer
|
||||
* @throws UnsupportedEncodingException the unsupported encoding exception
|
||||
*/
|
||||
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
|
||||
{
|
||||
return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,300 @@
|
|||
// ========================================================================
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content length.
|
||||
*
|
||||
* @param length the new content length
|
||||
*/
|
||||
public void setContentLength(long length)
|
||||
{
|
||||
_contentLength=length;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @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 )
|
||||
{
|
||||
_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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
|
|
@ -21,21 +21,17 @@ 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.http.gzip.GzipResponseWrapper;
|
||||
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;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -64,6 +60,7 @@ public class GzipHandler extends HandlerWrapper
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Instantiates a new gzip handler.
|
||||
*/
|
||||
public GzipHandler()
|
||||
{
|
||||
|
@ -199,6 +196,10 @@ public class GzipHandler extends HandlerWrapper
|
|||
_minGzipSize = minGzipSize;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.handler.HandlerWrapper#handle(java.lang.String, org.eclipse.jetty.server.Request, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
|
||||
*/
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
|
@ -218,7 +219,7 @@ public class GzipHandler extends HandlerWrapper
|
|||
}
|
||||
}
|
||||
|
||||
final GZIPResponseWrapper wrappedResponse = newGZIPResponseWrapper(request,response);
|
||||
final GzipResponseWrapper wrappedResponse = newGzipResponseWrapper(request,response);
|
||||
|
||||
boolean exceptional=true;
|
||||
try
|
||||
|
@ -265,435 +266,41 @@ public class GzipHandler extends HandlerWrapper
|
|||
}
|
||||
}
|
||||
|
||||
protected GZIPResponseWrapper newGZIPResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
return new GZIPResponseWrapper(request,response);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allows derived implementations to replace PrintWriter implementation
|
||||
/**
|
||||
* Allows derived implementations to replace ResponseWrapper implementation.
|
||||
*
|
||||
* @param request the request
|
||||
* @param response the response
|
||||
* @return the gzip response wrapper
|
||||
*/
|
||||
protected PrintWriter newWriter(OutputStream out, String encoding) throws UnsupportedEncodingException
|
||||
protected GzipResponseWrapper newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
return encoding == null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
|
||||
return new GzipResponseWrapper(request, response)
|
||||
{
|
||||
{
|
||||
_mimeTypes = GzipHandler.this._mimeTypes;
|
||||
_bufferSize = GzipHandler.this._bufferSize;
|
||||
_minGzipSize = GzipHandler.this._minGzipSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
|
||||
{
|
||||
return GzipHandler.this.newWriter(out,encoding);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public class GZIPResponseWrapper extends HttpServletResponseWrapper
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,537 +0,0 @@
|
|||
// ========================================================================
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -20,24 +20,20 @@ import java.io.UnsupportedEncodingException;
|
|||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
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.util.ByteArrayOutputStream2;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -65,11 +61,15 @@ import org.eclipse.jetty.util.log.Log;
|
|||
*/
|
||||
public class GzipFilter extends UserAgentFilter
|
||||
{
|
||||
protected Set _mimeTypes;
|
||||
protected Set<String> _mimeTypes;
|
||||
protected int _bufferSize=8192;
|
||||
protected int _minGzipSize=256;
|
||||
protected Set _excluded;
|
||||
protected Set<String> _excluded;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlets.UserAgentFilter#init(javax.servlet.FilterConfig)
|
||||
*/
|
||||
public void init(FilterConfig filterConfig) throws ServletException
|
||||
{
|
||||
super.init(filterConfig);
|
||||
|
@ -85,7 +85,7 @@ public class GzipFilter extends UserAgentFilter
|
|||
tmp=filterConfig.getInitParameter("mimeTypes");
|
||||
if (tmp!=null)
|
||||
{
|
||||
_mimeTypes=new HashSet();
|
||||
_mimeTypes=new HashSet<String>();
|
||||
StringTokenizer tok = new StringTokenizer(tmp,",",false);
|
||||
while (tok.hasMoreTokens())
|
||||
_mimeTypes.add(tok.nextToken());
|
||||
|
@ -94,17 +94,25 @@ public class GzipFilter extends UserAgentFilter
|
|||
tmp=filterConfig.getInitParameter("excludedAgents");
|
||||
if (tmp!=null)
|
||||
{
|
||||
_excluded=new HashSet();
|
||||
_excluded=new HashSet<String>();
|
||||
StringTokenizer tok = new StringTokenizer(tmp,",",false);
|
||||
while (tok.hasMoreTokens())
|
||||
_excluded.add(tok.nextToken());
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlets.UserAgentFilter#destroy()
|
||||
*/
|
||||
public void destroy()
|
||||
{
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlets.UserAgentFilter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
|
||||
*/
|
||||
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
|
@ -125,7 +133,7 @@ public class GzipFilter extends UserAgentFilter
|
|||
}
|
||||
}
|
||||
|
||||
final GZIPResponseWrapper wrappedResponse=newGZIPResponseWrapper(request,response);
|
||||
final GzipResponseWrapper wrappedResponse=newGzipResponseWrapper(request,response);
|
||||
|
||||
boolean exceptional=true;
|
||||
try
|
||||
|
@ -171,436 +179,41 @@ public class GzipFilter extends UserAgentFilter
|
|||
}
|
||||
}
|
||||
|
||||
protected GZIPResponseWrapper newGZIPResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
/**
|
||||
* 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);
|
||||
return new GzipResponseWrapper(request, response)
|
||||
{
|
||||
{
|
||||
_mimeTypes = GzipFilter.this._mimeTypes;
|
||||
_bufferSize = GzipFilter.this._bufferSize;
|
||||
_minGzipSize = 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
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ 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.io.UncheckedPrintWriter;
|
||||
|
||||
|
||||
|
@ -55,16 +57,20 @@ public class IncludableGzipFilter extends GzipFilter
|
|||
}
|
||||
|
||||
@Override
|
||||
protected GZIPResponseWrapper newGZIPResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
protected GzipResponseWrapper newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
return new IncludableResponseWrapper(request,response);
|
||||
}
|
||||
|
||||
public class IncludableResponseWrapper extends GzipFilter.GZIPResponseWrapper
|
||||
public class IncludableResponseWrapper extends GzipResponseWrapper
|
||||
{
|
||||
public IncludableResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
super(request,response);
|
||||
|
||||
_mimeTypes = IncludableGzipFilter.this._mimeTypes;
|
||||
_bufferSize = IncludableGzipFilter.this._bufferSize;
|
||||
_minGzipSize = IncludableGzipFilter.this._minGzipSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,9 +78,15 @@ public class IncludableGzipFilter extends GzipFilter
|
|||
{
|
||||
return new IncludableGzipStream(request,response,contentLength,bufferSize,minGzipSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
|
||||
{
|
||||
return IncludableGzipFilter.this.newWriter(out,encoding);
|
||||
}
|
||||
}
|
||||
|
||||
public class IncludableGzipStream extends GzipFilter.GzipStream
|
||||
public class IncludableGzipStream extends GzipStream
|
||||
{
|
||||
public IncludableGzipStream(HttpServletRequest request, HttpServletResponse response, long contentLength, int bufferSize, int minGzipSize)
|
||||
throws IOException
|
||||
|
@ -93,7 +105,7 @@ public class IncludableGzipFilter extends GzipFilter
|
|||
return _response.containsHeader("Content-Encoding");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
|
||||
{
|
||||
|
|
|
@ -13,21 +13,15 @@
|
|||
|
||||
package org.eclipse.jetty.servlets;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.StringReader;
|
||||
import java.net.Socket;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -43,9 +37,6 @@ import org.junit.Before;
|
|||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class GzipFilterTest
|
||||
{
|
||||
private static String __content =
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
// ========================================================================
|
||||
// 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.servlets;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.testing.HttpTester;
|
||||
import org.eclipse.jetty.testing.ServletTester;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
public class IncludableGzipFilterTest
|
||||
{
|
||||
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.";
|
||||
|
||||
@Rule
|
||||
public TestingDir testdir = new TestingDir();
|
||||
|
||||
private ServletTester tester;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
testdir.ensureEmpty();
|
||||
|
||||
File testFile = testdir.getFile("file.txt");
|
||||
BufferedOutputStream testOut = new BufferedOutputStream(new FileOutputStream(testFile));
|
||||
ByteArrayInputStream testIn = new ByteArrayInputStream(__content.getBytes("ISO8859_1"));
|
||||
IO.copy(testIn,testOut);
|
||||
testOut.close();
|
||||
|
||||
tester=new ServletTester();
|
||||
tester.setContextPath("/context");
|
||||
tester.setResourceBase(testdir.getDir().getCanonicalPath());
|
||||
tester.addServlet(org.eclipse.jetty.servlet.DefaultServlet.class, "/");
|
||||
FilterHolder holder = tester.addFilter(IncludableGzipFilter.class,"/*",0);
|
||||
holder.setInitParameter("mimeTypes","text/plain");
|
||||
tester.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception
|
||||
{
|
||||
tester.stop();
|
||||
IO.delete(testdir.getDir());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGzipFilter() 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("/context/file.txt");
|
||||
|
||||
ByteArrayBuffer reqsBuff = new ByteArrayBuffer(request.generate().getBytes());
|
||||
ByteArrayBuffer respBuff = tester.getResponses(reqsBuff);
|
||||
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("ISO8859_1"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue