354014 Content-Length is passed to wrapped response in GZipFilter

This commit is contained in:
Michael Gorovoy 2011-08-08 18:03:36 -04:00
parent 5e2583084d
commit d496a4f80a
8 changed files with 303 additions and 29 deletions

View File

@ -15,6 +15,7 @@ jetty-7.5.0-SNAPSHOT
+ 353465 JAASLoginService ignores callbackHandlerClass + 353465 JAASLoginService ignores callbackHandlerClass
+ 353563 HttpDestinationQueueTest too slow + 353563 HttpDestinationQueueTest too slow
+ 353862 Improve performance of QuotedStringTokenizer.quote() + 353862 Improve performance of QuotedStringTokenizer.quote()
+ 354014 Content-Length is passed to wrapped response in GZipFilter
jetty-7.4.4.v20110707 July 7th 2011 jetty-7.4.4.v20110707 July 7th 2011
+ 308851 Converted all jetty-client module tests to JUnit 4 + 308851 Converted all jetty-client module tests to JUnit 4

View File

@ -22,6 +22,7 @@ import java.io.UnsupportedEncodingException;
import java.util.Set; import java.util.Set;
import javax.servlet.ServletOutputStream; import javax.servlet.ServletOutputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper; import javax.servlet.http.HttpServletResponseWrapper;
@ -34,10 +35,13 @@ import org.eclipse.jetty.util.StringUtil;
*/ */
public class GzipResponseWrapper extends HttpServletResponseWrapper public class GzipResponseWrapper extends HttpServletResponseWrapper
{ {
public static int DEFAULT_BUFFER_SIZE = 8192;
public static int DEFAULT_MIN_GZIP_SIZE = 256;
private HttpServletRequest _request; private HttpServletRequest _request;
private Set<String> _mimeTypes; private Set<String> _mimeTypes;
private int _bufferSize=8192; private int _bufferSize=DEFAULT_BUFFER_SIZE;
private int _minGzipSize=256; private int _minGzipSize=DEFAULT_MIN_GZIP_SIZE;
private PrintWriter _writer; private PrintWriter _writer;
private GzipStream _gzStream; private GzipStream _gzStream;
@ -137,10 +141,28 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
* @see javax.servlet.ServletResponseWrapper#setContentLength(int) * @see javax.servlet.ServletResponseWrapper#setContentLength(int)
*/ */
public void setContentLength(int length) public void setContentLength(int length)
{
setContentLength((long)length);
}
/* ------------------------------------------------------------ */
protected void setContentLength(long length)
{ {
_contentLength=length; _contentLength=length;
if (_gzStream!=null) if (_gzStream!=null)
_gzStream.setContentLength(length); _gzStream.setContentLength(length);
else if (_noGzip && _contentLength>=0)
{
HttpServletResponse response = (HttpServletResponse)getResponse();
if(_contentLength<Integer.MAX_VALUE)
{
response.setContentLength((int)_contentLength);
}
else
{
response.setHeader("Content-Length", Long.toString(_contentLength));
}
}
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -179,9 +201,7 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
{ {
if ("content-length".equalsIgnoreCase(name)) if ("content-length".equalsIgnoreCase(name))
{ {
_contentLength=Long.parseLong(value); setContentLength(Long.parseLong(value));
if (_gzStream!=null)
_gzStream.setContentLength(_contentLength);
} }
else if ("content-type".equalsIgnoreCase(name)) else if ("content-type".equalsIgnoreCase(name))
{ {
@ -296,7 +316,10 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
if (_gzStream==null) if (_gzStream==null)
{ {
if (getResponse().isCommitted() || _noGzip) if (getResponse().isCommitted() || _noGzip)
{
setContentLength(_contentLength);
return getResponse().getOutputStream(); return getResponse().getOutputStream();
}
_gzStream=newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize); _gzStream=newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize);
} }
@ -318,7 +341,10 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
throw new IllegalStateException("getOutputStream() called"); throw new IllegalStateException("getOutputStream() called");
if (getResponse().isCommitted() || _noGzip) if (getResponse().isCommitted() || _noGzip)
{
setContentLength(_contentLength);
return getResponse().getWriter(); return getResponse().getWriter();
}
_gzStream=newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize); _gzStream=newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize);
_writer=newWriter(_gzStream,getCharacterEncoding()); _writer=newWriter(_gzStream,getCharacterEncoding());

View File

@ -42,6 +42,7 @@ public class GzipStream extends ServletOutputStream
protected int _bufferSize; protected int _bufferSize;
protected int _minGzipSize; protected int _minGzipSize;
protected long _contentLength; protected long _contentLength;
protected boolean _doNotGzip;
/** /**
* Instantiates a new gzip stream. * Instantiates a new gzip stream.
@ -77,6 +78,7 @@ public class GzipStream extends ServletOutputStream
if (_gzOut!=null) if (_gzOut!=null)
_response.setHeader("Content-Encoding",null); _response.setHeader("Content-Encoding",null);
_gzOut=null; _gzOut=null;
_doNotGzip=false;
} }
/** /**
@ -87,6 +89,13 @@ public class GzipStream extends ServletOutputStream
public void setContentLength(long length) public void setContentLength(long length)
{ {
_contentLength=length; _contentLength=length;
if (_doNotGzip && length>=0)
{
if(_contentLength<Integer.MAX_VALUE)
_response.setContentLength((int)_contentLength);
else
_response.setHeader("Content-Length",Long.toString(_contentLength));
}
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -245,14 +254,10 @@ public class GzipStream extends ServletOutputStream
throw new IllegalStateException(); throw new IllegalStateException();
if (_out==null || _bOut!=null ) if (_out==null || _bOut!=null )
{ {
_doNotGzip = true;
_out=_response.getOutputStream(); _out=_response.getOutputStream();
if (_contentLength>=0) setContentLength(_contentLength);
{
if(_contentLength<Integer.MAX_VALUE)
_response.setContentLength((int)_contentLength);
else
_response.setHeader("Content-Length",Long.toString(_contentLength));
}
if (_bOut!=null) if (_bOut!=null)
_out.write(_bOut.getBuf(),0,_bOut.getCount()); _out.write(_bOut.getBuf(),0,_bOut.getCount());

View File

@ -14,6 +14,7 @@
package org.eclipse.jetty.servlets; package org.eclipse.jetty.servlets;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
@ -26,6 +27,7 @@ import java.util.zip.GZIPInputStream;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
import org.eclipse.jetty.io.ByteArrayBuffer; import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.testing.HttpTester; import org.eclipse.jetty.testing.HttpTester;
@ -39,24 +41,37 @@ import org.junit.Test;
public class GzipFilterTest public class GzipFilterTest
{ {
private static String __content = public 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 "+ static
"habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "+ {
"Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam "+ // The size of content must be greater then
"at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate "+ // buffer size in GzipResponseWrapper class.
"velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. "+ StringBuilder builder = new StringBuilder();
"Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum "+ do
"eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa "+ {
"sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam "+ builder.append("Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. ");
"consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. "+ builder.append("Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque ");
"Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+ builder.append("habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. ");
"et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque."; builder.append("Vestibulum sit amet felis augue, vel convallis dolor. Cras accumsan vehicula diam ");
builder.append("at faucibus. Etiam in urna turpis, sed congue mi. Morbi et lorem eros. Donec vulputate ");
builder.append("velit in risus suscipit lobortis. Aliquam id urna orci, nec sollicitudin ipsum. ");
builder.append("Cras a orci turpis. Donec suscipit vulputate cursus. Mauris nunc tellus, fermentum ");
builder.append("eu auctor ut, mollis at diam. Quisque porttitor ultrices metus, vitae tincidunt massa ");
builder.append("sollicitudin a. Vivamus porttitor libero eget purus hendrerit cursus. Integer aliquam ");
builder.append("consequat mauris quis luctus. Cras enim nibh, dignissim eu faucibus ac, mollis nec neque. ");
builder.append("Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse ");
builder.append("et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.");
}
while (builder.length() < GzipResponseWrapper.DEFAULT_BUFFER_SIZE);
__content = builder.toString();
}
@Rule @Rule
public TestingDir testdir = new TestingDir(); public TestingDir testdir = new TestingDir();
private ServletTester tester; protected ServletTester tester;
@Before @Before
public void setUp() throws Exception public void setUp() throws Exception
@ -78,7 +93,7 @@ public class GzipFilterTest
tester=new ServletTester(); tester=new ServletTester();
tester.setContextPath("/context"); tester.setContextPath("/context");
tester.setResourceBase(testdir.getDir().getCanonicalPath()); tester.setResourceBase(testdir.getDir().getCanonicalPath());
tester.addServlet(org.eclipse.jetty.servlet.DefaultServlet.class, "/"); tester.addServlet(getServletClass(), "/");
FilterHolder holder = tester.addFilter(GzipFilter.class,"/*",0); FilterHolder holder = tester.addFilter(GzipFilter.class,"/*",0);
holder.setInitParameter("mimeTypes","text/plain"); holder.setInitParameter("mimeTypes","text/plain");
tester.start(); tester.start();
@ -91,6 +106,11 @@ public class GzipFilterTest
IO.delete(testdir.getDir()); IO.delete(testdir.getDir());
} }
public Class<?> getServletClass()
{
return org.eclipse.jetty.servlet.DefaultServlet.class;
}
@Test @Test
public void testGzip() throws Exception public void testGzip() throws Exception
{ {
@ -109,6 +129,7 @@ public class GzipFilterTest
response.parse(respBuff.asArray()); response.parse(respBuff.asArray());
assertTrue(response.getMethod()==null); assertTrue(response.getMethod()==null);
assertNotNull("Content-Length header is missing", response.getHeader("Content-Length"));
assertTrue(response.getHeader("Content-Encoding").equalsIgnoreCase("gzip")); assertTrue(response.getHeader("Content-Encoding").equalsIgnoreCase("gzip"));
assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertEquals(HttpServletResponse.SC_OK,response.getStatus());
@ -137,6 +158,7 @@ public class GzipFilterTest
response.parse(respBuff.asArray()); response.parse(respBuff.asArray());
assertTrue(response.getMethod()==null); assertTrue(response.getMethod()==null);
assertNotNull("Content-Length header is missing", response.getHeader("Content-Length"));
assertEquals(__content.getBytes().length, Integer.parseInt(response.getHeader("Content-Length"))); assertEquals(__content.getBytes().length, Integer.parseInt(response.getHeader("Content-Length")));
assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertEquals(HttpServletResponse.SC_OK,response.getStatus());

View File

@ -0,0 +1,56 @@
// ========================================================================
// 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 java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GzipFilterTest1 extends GzipFilterTest
{
@Override
public Class<?> getServletClass()
{
return TestServlet.class;
}
public static class TestServlet extends HttpServlet
{
private static final long serialVersionUID = -3603297003496724934L;
/* ------------------------------------------------------------ */
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
byte[] dataBytes = GzipFilterTest.__content.getBytes("ISO8859_1");
ServletOutputStream out = response.getOutputStream();
response.setContentLength(dataBytes.length);
String fileName = request.getServletPath();
if (fileName.endsWith("txt"))
response.setContentType("text/plain");
else if (fileName.endsWith("mp3"))
response.setContentType("audio/mpeg");
out.write(dataBytes);
}
}
}

View File

@ -0,0 +1,54 @@
// ========================================================================
// 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 java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GzipFilterTest2 extends GzipFilterTest
{
@Override
public Class<?> getServletClass()
{
return TestServlet.class;
}
public static class TestServlet extends HttpServlet
{
private static final long serialVersionUID = -3603297003496724934L;
/* ------------------------------------------------------------ */
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
byte[] dataBytes = GzipFilterTest.__content.getBytes("ISO8859_1");
response.setContentLength(dataBytes.length);
String fileName = request.getServletPath();
if (fileName.endsWith("txt"))
response.setContentType("text/plain");
else if (fileName.endsWith("mp3"))
response.setContentType("audio/mpeg");
ServletOutputStream out = response.getOutputStream();
out.write(dataBytes);
}
}
}

View File

@ -0,0 +1,56 @@
// ========================================================================
// 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 java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GzipFilterTest3 extends GzipFilterTest
{
@Override
public Class<?> getServletClass()
{
return TestServlet.class;
}
public static class TestServlet extends HttpServlet
{
private static final long serialVersionUID = -3603297003496724934L;
/* ------------------------------------------------------------ */
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
byte[] dataBytes = GzipFilterTest.__content.getBytes("ISO8859_1");
ServletOutputStream out = response.getOutputStream();
String fileName = request.getServletPath();
if (fileName.endsWith("txt"))
response.setContentType("text/plain");
else if (fileName.endsWith("mp3"))
response.setContentType("audio/mpeg");
response.setContentLength(dataBytes.length);
out.write(dataBytes);
}
}
}

View File

@ -0,0 +1,54 @@
// ========================================================================
// 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 java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GzipFilterTest4 extends GzipFilterTest
{
@Override
public Class<?> getServletClass()
{
return TestServlet.class;
}
public static class TestServlet extends HttpServlet
{
private static final long serialVersionUID = -3603297003496724934L;
/* ------------------------------------------------------------ */
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
byte[] dataBytes = GzipFilterTest.__content.getBytes("ISO8859_1");
String fileName = request.getServletPath();
if (fileName.endsWith("txt"))
response.setContentType("text/plain");
else if (fileName.endsWith("mp3"))
response.setContentType("audio/mpeg");
response.setContentLength(dataBytes.length);
ServletOutputStream out = response.getOutputStream();
out.write(dataBytes);
}
}
}