Merge remote-tracking branch 'origin/jetty-8'
Conflicts: VERSION.txt aggregates/jetty-all/pom.xml examples/async-rest/async-rest-jar/pom.xml examples/async-rest/async-rest-webapp/pom.xml examples/async-rest/pom.xml examples/embedded/pom.xml jetty-aggregate/jetty-all-server/pom.xml jetty-aggregate/jetty-client/pom.xml jetty-aggregate/jetty-server/pom.xml jetty-aggregate/jetty-servlet/pom.xml jetty-aggregate/jetty-webapp/pom.xml jetty-aggregate/jetty-websocket/pom.xml jetty-aggregate/pom.xml jetty-annotations/pom.xml jetty-client/pom.xml jetty-continuation/pom.xml jetty-deploy/pom.xml jetty-distribution/pom.xml jetty-http-spi/pom.xml jetty-http/pom.xml jetty-io/pom.xml jetty-jaspi/pom.xml jetty-jmx/pom.xml jetty-jndi/pom.xml jetty-jsp/pom.xml jetty-monitor/pom.xml jetty-nosql/pom.xml jetty-osgi/jetty-osgi-boot-jsp/pom.xml jetty-osgi/jetty-osgi-boot-warurl/pom.xml jetty-osgi/jetty-osgi-boot/pom.xml jetty-osgi/jetty-osgi-httpservice/pom.xml jetty-osgi/pom.xml jetty-osgi/test-jetty-osgi-context/pom.xml jetty-osgi/test-jetty-osgi-webapp/pom.xml jetty-osgi/test-jetty-osgi/pom.xml jetty-overlay-deployer/pom.xml jetty-plus/pom.xml jetty-policy/pom.xml jetty-proxy/pom.xml jetty-rewrite/pom.xml jetty-runner/pom.xml jetty-security/pom.xml jetty-server/pom.xml jetty-servlet/pom.xml jetty-servlets/pom.xml jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/CompressedResponseWrapper.java jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipWithPipeliningTest.java jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java jetty-spdy/pom.xml jetty-spdy/spdy-client/pom.xml jetty-spdy/spdy-core/pom.xml jetty-spdy/spdy-example-webapp/pom.xml jetty-spdy/spdy-server/pom.xml jetty-start/pom.xml jetty-util-ajax/pom.xml jetty-util/pom.xml jetty-webapp/pom.xml jetty-websocket/pom.xml jetty-xml/pom.xml pom.xml test-continuation-jetty6/pom.xml test-continuation/pom.xml test-jetty-nested/pom.xml test-jetty-servlet/pom.xml test-jetty-servlet/src/main/java/org/eclipse/jetty/testing/HttpTester.java tests/pom.xml tests/test-integration/pom.xml tests/test-loginservice/pom.xml tests/test-sessions/pom.xml tests/test-sessions/test-hash-sessions/pom.xml tests/test-sessions/test-jdbc-sessions/pom.xml tests/test-sessions/test-mongodb-sessions/pom.xml tests/test-sessions/test-sessions-common/pom.xml tests/test-webapps/pom.xml tests/test-webapps/test-jetty-webapp/pom.xml tests/test-webapps/test-webapp-rfc2616/pom.xml
This commit is contained in:
commit
45d4cd3fcd
55
VERSION.txt
55
VERSION.txt
|
@ -1,3 +1,5 @@
|
|||
jetty-9.0.4-SNAPSHOT
|
||||
|
||||
jetty-9.0.3.v20130506 06 May 2013
|
||||
+ 404010 fix cast exception in mongodb session manager
|
||||
+ 404911 WebSocketCloseTest fails spuriously
|
||||
|
@ -164,6 +166,34 @@ jetty-9.0.0.v20130308 - 08 March 2013
|
|||
+ 402757 WebSocket client module can't be used with WebSocket server module in
|
||||
the same WAR
|
||||
|
||||
jetty-8.1.11.v20130520 - 20 May 2013
|
||||
+ 402844 STOP.PORT & STOP.KEY behaviour has changed
|
||||
+ 403281 jetty.sh waits for started or failure before returning
|
||||
+ 403513 jetty:run goal cannot be executed twice during the maven build
|
||||
+ 403570 Asynchronous Request Logging
|
||||
+ 404010 fix cast exception in mongodb session manager
|
||||
+ 404128 Add Vary headers rather than set them
|
||||
+ 404283 org.eclipse.jetty.util.Scanner.scanFile() dies with an NPE if
|
||||
listFiles() returns null
|
||||
+ 404325 data constraint redirection does send default port
|
||||
+ 404517 Close connection if request received after half close
|
||||
+ 404789 Support IPv6 addresses in DoSFilter white list.
|
||||
+ 404958 Fixed Resource.newSystemResource striped / handling
|
||||
+ 405281 allow filemappedbuffers to not be used
|
||||
+ 405537 NPE in rendering JSP using SPDY and wrapped ServletRequest
|
||||
+ 406437 Digest Auth supports out of order nc
|
||||
+ 406618 Jetty startup in OSGi Equinox fails when using option
|
||||
jetty.home.bundle=org.eclipse.jetty.osgi.boot
|
||||
+ 406923 CR line termination
|
||||
+ 407136 @PreDestroy called after Servlet.destroy()
|
||||
+ 407173 java.lang.IllegalStateException: null when using JDBCSessionManager
|
||||
+ 407931 Add toggle for failing on servlet availability
|
||||
+ 407976 JDBCSessionIdManager potentially leaves server in bad state after
|
||||
startup
|
||||
+ 408077 HashSessionManager leaves file handles open after being stopped
|
||||
+ 408446 Multipart parsing issue with boundry and charset in ContentType
|
||||
header
|
||||
|
||||
jetty-8.1.10.v20130312 - 12 March 2013
|
||||
+ 376273 Early EOF because of SSL Protocol Error on
|
||||
https://api-3t.paypal.com/nvp.
|
||||
|
@ -200,6 +230,31 @@ jetty-8.1.10.v20130312 - 12 March 2013
|
|||
+ 402833 Test harness for global error page and hide exception message from
|
||||
reason string
|
||||
|
||||
jetty-7.6.11.v20130520 - 20 May 2013
|
||||
+ 402844 STOP.PORT & STOP.KEY behaviour has changed
|
||||
+ 403281 jetty.sh waits for started or failure before returning
|
||||
+ 403513 jetty:run goal cannot be executed twice during the maven build
|
||||
+ 403570 Asynchronous Request Logging
|
||||
+ 404010 fix cast exception in mongodb session manager
|
||||
+ 404128 Add Vary headers rather than set them
|
||||
+ 404283 org.eclipse.jetty.util.Scanner.scanFile() dies with an NPE if
|
||||
listFiles() returns null
|
||||
+ 404325 data constraint redirection does send default port
|
||||
+ 404517 Close connection if request received after half close
|
||||
+ 404789 Support IPv6 addresses in DoSFilter white list.
|
||||
+ 404958 Fixed Resource.newSystemResource striped / handling
|
||||
+ 405281 allow filemappedbuffers to not be used
|
||||
+ 405537 NPE in rendering JSP using SPDY and wrapped ServletRequest
|
||||
+ 406437 Digest Auth supports out of order nc
|
||||
+ 406923 CR line termination
|
||||
+ 407136 @PreDestroy called after Servlet.destroy()
|
||||
+ 407173 java.lang.IllegalStateException: null when using JDBCSessionManager
|
||||
+ 407976 JDBCSessionIdManager potentially leaves server in bad state after
|
||||
startup
|
||||
+ 408077 HashSessionManager leaves file handles open after being stopped
|
||||
+ 408446 Multipart parsing issue with boundry and charset in ContentType
|
||||
header
|
||||
|
||||
jetty-7.6.10.v20130312 - 12 March 2013
|
||||
+ 376273 Early EOF because of SSL Protocol Error on
|
||||
https://api-3t.paypal.com/nvp.
|
||||
|
|
|
@ -65,22 +65,31 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
|||
doCompress();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Reset buffer.
|
||||
*/
|
||||
public void resetBuffer()
|
||||
{
|
||||
if (_response.isCommitted())
|
||||
if (_response.isCommitted() || _compressedOutputStream!=null )
|
||||
throw new IllegalStateException("Committed");
|
||||
_closed = false;
|
||||
_out = null;
|
||||
_bOut = null;
|
||||
if (_compressedOutputStream != null)
|
||||
_response.setHeader("Content-Encoding",null);
|
||||
_compressedOutputStream = null;
|
||||
_doNotCompress = false;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setBufferSize(int bufferSize)
|
||||
{
|
||||
if (_bOut!=null && _bOut.getBuf().length<bufferSize)
|
||||
{
|
||||
ByteArrayOutputStream2 b = new ByteArrayOutputStream2(bufferSize);
|
||||
b.write(_bOut.getBuf(),0,_bOut.size());
|
||||
_bOut=b;
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setContentLength()
|
||||
{
|
||||
|
@ -170,7 +179,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
|||
if (_out == null || _bOut != null)
|
||||
{
|
||||
long length=_wrapper.getContentLength();
|
||||
if (length > 0 && length < _wrapper.getMinCompressSize())
|
||||
if (length >= 0 && length < _wrapper.getMinCompressSize())
|
||||
doNotCompress(false);
|
||||
else
|
||||
doCompress();
|
||||
|
@ -359,4 +368,5 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
|||
*/
|
||||
protected abstract DeflaterOutputStream createStream() throws IOException;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -108,6 +108,8 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
public void setBufferSize(int bufferSize)
|
||||
{
|
||||
_bufferSize = bufferSize;
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.setBufferSize(bufferSize);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -128,7 +130,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
{
|
||||
super.setContentType(ct);
|
||||
|
||||
if (_compressedStream==null || _compressedStream.getOutputStream()==null)
|
||||
if (!_noCompression && (_compressedStream==null || _compressedStream.getOutputStream()==null))
|
||||
{
|
||||
if (ct!=null)
|
||||
{
|
||||
|
@ -174,7 +176,10 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
@Override
|
||||
public void setContentLength(int length)
|
||||
{
|
||||
setContentLength((long)length);
|
||||
if (_noCompression)
|
||||
super.setContentLength(length);
|
||||
else
|
||||
setContentLength((long)length);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -312,6 +317,8 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
*/
|
||||
public void noCompression()
|
||||
{
|
||||
if (!_noCompression)
|
||||
setDeferredHeaders();
|
||||
_noCompression=true;
|
||||
if (_compressedStream!=null)
|
||||
{
|
||||
|
@ -336,6 +343,25 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
_writer.flush();
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.finish();
|
||||
else
|
||||
setDeferredHeaders();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
private void setDeferredHeaders()
|
||||
{
|
||||
if (!isCommitted())
|
||||
{
|
||||
if (_contentLength>=0)
|
||||
{
|
||||
if (_contentLength < Integer.MAX_VALUE)
|
||||
super.setContentLength((int)_contentLength);
|
||||
else
|
||||
super.setHeader("Content-Length",Long.toString(_contentLength));
|
||||
}
|
||||
if(_etag!=null)
|
||||
super.setHeader("ETag",_etag);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -345,7 +371,9 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
@Override
|
||||
public void setHeader(String name, String value)
|
||||
{
|
||||
if ("content-length".equalsIgnoreCase(name))
|
||||
if (_noCompression)
|
||||
super.setHeader(name,value);
|
||||
else if ("content-length".equalsIgnoreCase(name))
|
||||
{
|
||||
setContentLength(Long.parseLong(value));
|
||||
}
|
||||
|
@ -371,7 +399,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
@Override
|
||||
public boolean containsHeader(String name)
|
||||
{
|
||||
if ("etag".equalsIgnoreCase(name) && _etag!=null)
|
||||
if (!_noCompression && "etag".equalsIgnoreCase(name) && _etag!=null)
|
||||
return true;
|
||||
return super.containsHeader(name);
|
||||
}
|
||||
|
@ -386,10 +414,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
if (_compressedStream==null)
|
||||
{
|
||||
if (getResponse().isCommitted() || _noCompression)
|
||||
{
|
||||
setContentLength(_contentLength);
|
||||
return getResponse().getOutputStream();
|
||||
}
|
||||
|
||||
_compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse());
|
||||
}
|
||||
|
@ -412,10 +437,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
throw new IllegalStateException("getOutputStream() called");
|
||||
|
||||
if (getResponse().isCommitted() || _noCompression)
|
||||
{
|
||||
setContentLength(_contentLength);
|
||||
return getResponse().getWriter();
|
||||
}
|
||||
|
||||
_compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse());
|
||||
_writer=newWriter(_compressedStream,getCharacterEncoding());
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.List;
|
|||
import javax.servlet.Servlet;
|
||||
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.HttpTester;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlets.gzip.CompressedResponseWrapper;
|
||||
import org.eclipse.jetty.servlets.gzip.GzipTester;
|
||||
|
@ -35,6 +36,8 @@ import org.eclipse.jetty.servlets.gzip.TestServletStreamTypeLengthWrite;
|
|||
import org.eclipse.jetty.servlets.gzip.TestServletTypeLengthStreamWrite;
|
||||
import org.eclipse.jetty.servlets.gzip.TestServletTypeStreamLengthWrite;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
@ -132,7 +135,8 @@ public class GzipFilterContentLengthTest
|
|||
try
|
||||
{
|
||||
tester.start();
|
||||
tester.assertIsResponseNotGzipCompressed("GET",testfile.getName(),filesize,HttpStatus.OK_200);
|
||||
HttpTester.Response response = tester.assertIsResponseNotGzipCompressed("GET",testfile.getName(),filesize,HttpStatus.OK_200);
|
||||
Assert.assertThat(response.get("ETAG"),Matchers.startsWith("W/etag-"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -140,6 +144,15 @@ public class GzipFilterContentLengthTest
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests gzip compression of a small size file
|
||||
*/
|
||||
@Test
|
||||
public void testEmpty() throws Exception
|
||||
{
|
||||
assertIsNotGzipCompressed("empty.txt",0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests gzip compression of a small size file
|
||||
*/
|
||||
|
|
|
@ -79,6 +79,7 @@ public class GzipFilterDefaultTest
|
|||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
resp.setStatus(_status);
|
||||
resp.setHeader("ETag","W/\"204\"");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -141,11 +142,40 @@ public class GzipFilterDefaultTest
|
|||
@Override
|
||||
public void service(HttpServletRequest req, HttpServletResponse resp) throws IOException,ServletException
|
||||
{
|
||||
String uri=req.getRequestURI();
|
||||
if (uri.endsWith(".deferred"))
|
||||
{
|
||||
System.err.println("type for "+uri.substring(0,uri.length()-9)+" is "+getServletContext().getMimeType(uri.substring(0,uri.length()-9)));
|
||||
resp.setContentType(getServletContext().getMimeType(uri.substring(0,uri.length()-9)));
|
||||
}
|
||||
|
||||
doGet(req,resp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testIsGzipCompressedEmpty() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
// Test content that is smaller than the buffer.
|
||||
tester.prepareServerFile("empty.txt",0);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(org.eclipse.jetty.servlet.DefaultServlet.class);
|
||||
holder.setInitParameter("mimeTypes","text/plain");
|
||||
|
||||
try
|
||||
{
|
||||
tester.start();
|
||||
HttpTester.Response http = tester.assertIsResponseNotGzipCompressed("GET","empty.txt",0,200);
|
||||
}
|
||||
finally
|
||||
{
|
||||
tester.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsGzipCompressedTiny() throws Exception
|
||||
|
@ -267,7 +297,7 @@ public class GzipFilterDefaultTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testIsNotGzipCompressed() throws Exception
|
||||
public void testIsNotGzipCompressedByContentType() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
|
@ -289,6 +319,29 @@ public class GzipFilterDefaultTest
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsNotGzipCompressedByDeferredContentType() throws Exception
|
||||
{
|
||||
GzipTester tester = new GzipTester(testingdir, compressionType);
|
||||
|
||||
int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
|
||||
tester.prepareServerFile("file.mp3.deferred",filesize);
|
||||
|
||||
FilterHolder holder = tester.setContentServlet(GetServlet.class);
|
||||
holder.setInitParameter("mimeTypes","text/plain");
|
||||
|
||||
try
|
||||
{
|
||||
tester.start();
|
||||
HttpTester.Response http = tester.assertIsResponseNotGzipCompressed("GET","file.mp3.deferred", filesize, HttpStatus.OK_200);
|
||||
Assert.assertNull(http.get("Vary"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
tester.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsNotGzipCompressedHttpStatus() throws Exception
|
||||
{
|
||||
|
|
|
@ -1,258 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2013 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.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.security.DigestOutputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.Inflater;
|
||||
import java.util.zip.InflaterInputStream;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
|
||||
import org.eclipse.jetty.server.NetworkConnector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.DefaultServlet;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.servlets.gzip.Hex;
|
||||
import org.eclipse.jetty.servlets.gzip.NoOpOutputStream;
|
||||
import org.eclipse.jetty.toolchain.test.IO;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
/**
|
||||
* Test the effects of Gzip filtering when in the context of HTTP/1.1 Pipelining.
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class GzipWithPipeliningTest
|
||||
{
|
||||
@Parameters
|
||||
public static Collection<String[]> data()
|
||||
{
|
||||
// Test different Content-Encoding header combinations. So implicitly testing that gzip is preferred oder deflate
|
||||
String[][] data = new String[][]
|
||||
{
|
||||
{ GzipFilter.GZIP },
|
||||
{ GzipFilter.DEFLATE + ", " + GzipFilter.GZIP },
|
||||
{ GzipFilter.GZIP + ", " + GzipFilter.DEFLATE },
|
||||
{ GzipFilter.DEFLATE }
|
||||
};
|
||||
|
||||
return Arrays.asList(data);
|
||||
}
|
||||
|
||||
@Rule
|
||||
public TestingDir testingdir = new TestingDir();
|
||||
|
||||
private Server server;
|
||||
private URI serverUri;
|
||||
private String encodingHeader;
|
||||
|
||||
|
||||
public GzipWithPipeliningTest(String encodingHeader)
|
||||
{
|
||||
this.encodingHeader = encodingHeader;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void startServer() throws Exception
|
||||
{
|
||||
// Configure Server
|
||||
server = new Server(0);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
|
||||
DefaultServlet servlet = new DefaultServlet();
|
||||
ServletHolder holder = new ServletHolder(servlet);
|
||||
holder.setInitParameter("resourceBase",MavenTestingUtils.getTestResourcesDir().getAbsolutePath());
|
||||
context.addServlet(holder,"/");
|
||||
|
||||
FilterHolder filter = context.addFilter(GzipFilter.class,"/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
filter.setInitParameter("mimeTypes","text/plain");
|
||||
|
||||
server.setHandler(context);
|
||||
|
||||
// Start Server
|
||||
server.start();
|
||||
|
||||
serverUri = server.getURI();
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGzipThenImagePipelining() throws Exception
|
||||
{
|
||||
testingdir.ensureEmpty();
|
||||
File outputDir = testingdir.getDir();
|
||||
|
||||
PipelineHelper client = new PipelineHelper(serverUri, encodingHeader);
|
||||
|
||||
try
|
||||
{
|
||||
File txtFile = MavenTestingUtils.getTestResourceFile("lots-of-fantasy-names.txt");
|
||||
File pngFile = MavenTestingUtils.getTestResourceFile("jetty_logo.png");
|
||||
|
||||
// Size of content, as it exists on disk, without gzip compression.
|
||||
long rawsize = txtFile.length() + pngFile.length();
|
||||
assertThat("Ensure that we have sufficient file size to trigger chunking",rawsize,greaterThan(300000L));
|
||||
|
||||
String respHeader;
|
||||
|
||||
client.connect();
|
||||
|
||||
// Request text that will be gzipped + chunked in the response
|
||||
client.issueGET("/lots-of-fantasy-names.txt",true, false);
|
||||
|
||||
respHeader = client.readResponseHeader();
|
||||
//System.out.println("Response Header #1 --\n" + respHeader);
|
||||
String expectedEncodingHeader = encodingHeader.equals(GzipFilter.DEFLATE) ? GzipFilter.DEFLATE : GzipFilter.GZIP;
|
||||
assertThat("Content-Encoding should be gzipped",respHeader,containsString("Content-Encoding: " + expectedEncodingHeader + "\r\n"));
|
||||
assertThat("Transfer-Encoding should be chunked",respHeader,containsString("Transfer-Encoding: chunked\r\n"));
|
||||
|
||||
// Raw output / gzipped, writted to disk (checked for sha1sum later)
|
||||
File rawOutputFile = new File(outputDir, "response-1.gz");
|
||||
FileOutputStream rawOutputStream = new FileOutputStream(rawOutputFile);
|
||||
|
||||
long chunkSize = client.readChunkSize();
|
||||
//System.out.println("Chunk Size: " + chunkSize);
|
||||
|
||||
// Read only 20% - intentionally a partial read.
|
||||
//System.out.println("Attempting to read partial content ...");
|
||||
int readBytes = client.readBody(rawOutputStream,(int)(chunkSize * 0.20f));
|
||||
//System.out.printf("Read %,d bytes%n",readBytes);
|
||||
|
||||
// Issue another request
|
||||
client.issueGET("/jetty_logo.png",true, false);
|
||||
|
||||
// Finish reading chunks
|
||||
//System.out.println("Finish reading remaining chunks ...");
|
||||
String line;
|
||||
chunkSize = chunkSize - readBytes;
|
||||
while (chunkSize > 0)
|
||||
{
|
||||
readBytes = client.readBody(rawOutputStream,(int)chunkSize);
|
||||
//System.out.printf("Read %,d bytes%n",readBytes);
|
||||
line = client.readLine();
|
||||
assertThat("Chunk delim should be an empty line with CR+LF",line,is(""));
|
||||
chunkSize = client.readChunkSize();
|
||||
//System.out.printf("Next Chunk: (0x%X) %,d bytes%n",chunkSize,chunkSize);
|
||||
}
|
||||
|
||||
// Inter-pipeline delim
|
||||
line = client.readLine();
|
||||
assertThat("Inter-pipeline delim should be an empty line with CR+LF",line,is(""));
|
||||
|
||||
// Sha1tracking for 1st Request
|
||||
MessageDigest digestTxt = MessageDigest.getInstance("SHA1");
|
||||
DigestOutputStream digesterTxt = new DigestOutputStream(new NoOpOutputStream(),digestTxt);
|
||||
|
||||
// Decompress 1st request and calculate sha1sum
|
||||
IO.close(rawOutputStream);
|
||||
FileInputStream rawInputStream = new FileInputStream(rawOutputFile);
|
||||
InputStream uncompressedStream = null;
|
||||
if (GzipFilter.DEFLATE.equals(encodingHeader))
|
||||
{
|
||||
uncompressedStream = new InflaterInputStream(rawInputStream, new Inflater(true));
|
||||
}
|
||||
else
|
||||
{
|
||||
uncompressedStream = new GZIPInputStream(rawInputStream);
|
||||
}
|
||||
|
||||
IO.copy(uncompressedStream, digesterTxt);
|
||||
|
||||
// Read 2nd request http response header
|
||||
respHeader = client.readResponseHeader();
|
||||
//System.out.println("Response Header #2 --\n" + respHeader);
|
||||
assertThat("Content-Encoding should NOT be gzipped",respHeader,not(containsString("Content-Encoding: gzip\r\n")));
|
||||
assertThat("Transfer-Encoding should NOT be chunked",respHeader,not(containsString("Transfer-Encoding: chunked\r\n")));
|
||||
|
||||
// Sha1tracking for 2nd Request
|
||||
MessageDigest digestImg = MessageDigest.getInstance("SHA1");
|
||||
DigestOutputStream digesterImg = new DigestOutputStream(new NoOpOutputStream(),digestImg);
|
||||
|
||||
// Read 2nd request body
|
||||
int contentLength = client.getContentLength(respHeader);
|
||||
assertThat("Image Content Length",(long)contentLength,is(pngFile.length()));
|
||||
client.readBody(digesterImg,contentLength);
|
||||
|
||||
// Validate checksums
|
||||
IO.close(rawOutputStream);
|
||||
assertChecksum("lots-of-fantasy-names.txt",digestTxt);
|
||||
IO.close(digesterImg);
|
||||
assertChecksum("jetty_logo.png",digestImg);
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private void assertChecksum(String testResourceFile, MessageDigest digest) throws IOException
|
||||
{
|
||||
String expectedSha1 = loadSha1sum(testResourceFile + ".sha1");
|
||||
String actualSha1 = Hex.asHex(digest.digest());
|
||||
assertEquals(testResourceFile + " / SHA1Sum of content",expectedSha1,actualSha1);
|
||||
}
|
||||
|
||||
private String loadSha1sum(String testResourceSha1Sum) throws IOException
|
||||
{
|
||||
File sha1File = MavenTestingUtils.getTestResourceFile(testResourceSha1Sum);
|
||||
String contents = IO.readToString(sha1File);
|
||||
Pattern pat = Pattern.compile("^[0-9A-Fa-f]*");
|
||||
Matcher mat = pat.matcher(contents);
|
||||
assertTrue("Should have found HEX code in SHA1 file: " + sha1File,mat.find());
|
||||
return mat.group();
|
||||
}
|
||||
|
||||
}
|
|
@ -55,6 +55,7 @@ import org.eclipse.jetty.servlets.GzipFilter;
|
|||
import org.eclipse.jetty.toolchain.test.IO;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Assert;
|
||||
|
||||
public class GzipTester
|
||||
|
@ -105,6 +106,8 @@ public class GzipTester
|
|||
else
|
||||
Assert.assertThat("Response.header[Content-Encoding]", response.get("Content-Encoding"),containsString(compressionType.substring(0,qindex)));
|
||||
|
||||
Assert.assertThat(response.get("ETag"),Matchers.startsWith("W/"));
|
||||
|
||||
// Assert that the decompressed contents are what we expect.
|
||||
File serverFile = testdir.getFile(serverFilename);
|
||||
String expected = IO.readToString(serverFile);
|
||||
|
@ -182,6 +185,8 @@ public class GzipTester
|
|||
Assert.assertThat(prefix + ".header[Content-Type] (should have a Content-Type associated with it)",response.get("Content-Type"),notNullValue());
|
||||
Assert.assertThat(prefix + ".header[Content-Type]",response.get("Content-Type"),is(expectedContentType));
|
||||
|
||||
Assert.assertThat(response.get("ETAG"),Matchers.startsWith("W/"));
|
||||
|
||||
ByteArrayInputStream bais = null;
|
||||
DigestOutputStream digester = null;
|
||||
try
|
||||
|
@ -308,6 +313,10 @@ public class GzipTester
|
|||
int serverLength = Integer.parseInt(response.get("Content-Length"));
|
||||
Assert.assertEquals(serverLength,expectedFilesize);
|
||||
}
|
||||
|
||||
if (status>=200 && status<300)
|
||||
Assert.assertThat(response.get("ETAG"),Matchers.startsWith("W/"));
|
||||
|
||||
}
|
||||
Assert.assertThat("Response.header[Content-Encoding]",response.get("Content-Encoding"),not(containsString(compressionType)));
|
||||
}
|
||||
|
@ -337,11 +346,11 @@ public class GzipTester
|
|||
ByteArrayOutputStream out = null;
|
||||
try
|
||||
{
|
||||
in = new ByteArrayInputStream(response.getContentBytes());
|
||||
out = new ByteArrayOutputStream();
|
||||
IO.copy(in,out);
|
||||
|
||||
actual = out.toString(encoding);
|
||||
byte[] content=response.getContentBytes();
|
||||
if (content!=null)
|
||||
actual=new String(response.getContentBytes(),encoding);
|
||||
else
|
||||
actual="";
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -424,7 +433,7 @@ public class GzipTester
|
|||
finally
|
||||
{
|
||||
IO.close(in);
|
||||
IO.close(fos);
|
||||
IO.close(fos);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -456,6 +465,7 @@ public class GzipTester
|
|||
tester.setResourceBase(testdir.getDir().getCanonicalPath());
|
||||
ServletHolder servletHolder = tester.addServlet(servletClass,"/");
|
||||
servletHolder.setInitParameter("baseDir",testdir.getDir().getAbsolutePath());
|
||||
servletHolder.setInitParameter("etags","true");
|
||||
FilterHolder holder = tester.addFilter(gzipFilterClass,"/*",EnumSet.allOf(DispatcherType.class));
|
||||
holder.setInitParameter("vary","Accept-Encoding");
|
||||
return holder;
|
||||
|
|
|
@ -50,6 +50,7 @@ public class TestMinGzipSizeServlet extends TestDirContentServlet
|
|||
byte[] dataBytes = loadContentFileBytes(fileName);
|
||||
|
||||
response.setContentLength(dataBytes.length);
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
if (fileName.endsWith(".js"))
|
||||
{
|
||||
// intentionally long-form content type to test ";" splitting in code
|
||||
|
|
|
@ -59,6 +59,7 @@ public class TestServletLengthStreamTypeWrite extends TestDirContentServlet
|
|||
response.setContentType("text/plain");
|
||||
else if (fileName.endsWith("mp3"))
|
||||
response.setContentType("audio/mpeg");
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
|
||||
out.write(dataBytes);
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ public class TestServletLengthTypeStreamWrite extends TestDirContentServlet
|
|||
response.setContentType("text/plain");
|
||||
else if (fileName.endsWith("mp3"))
|
||||
response.setContentType("audio/mpeg");
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
out.write(dataBytes);
|
||||
|
|
|
@ -59,6 +59,7 @@ public class TestServletStreamLengthTypeWrite extends TestDirContentServlet
|
|||
response.setContentType("text/plain");
|
||||
else if (fileName.endsWith("mp3"))
|
||||
response.setContentType("audio/mpeg");
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
|
||||
out.write(dataBytes);
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ public class TestServletStreamTypeLengthWrite extends TestDirContentServlet
|
|||
response.setContentType("text/plain");
|
||||
else if (fileName.endsWith("mp3"))
|
||||
response.setContentType("audio/mpeg");
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
|
||||
response.setContentLength(dataBytes.length);
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ public class TestServletTypeLengthStreamWrite extends TestDirContentServlet
|
|||
response.setContentType("text/plain");
|
||||
else if (fileName.endsWith("mp3"))
|
||||
response.setContentType("audio/mpeg");
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
|
||||
response.setContentLength(dataBytes.length);
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ public class TestServletTypeStreamLengthWrite extends TestDirContentServlet
|
|||
response.setContentType("text/plain");
|
||||
else if (fileName.endsWith("mp3"))
|
||||
response.setContentType("audio/mpeg");
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
|
||||
ServletOutputStream out = response.getOutputStream();
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ public class TestStaticMimeTypeServlet extends TestDirContentServlet
|
|||
byte[] dataBytes = loadContentFileBytes(fileName);
|
||||
|
||||
response.setContentLength(dataBytes.length);
|
||||
response.setHeader("ETag","W/etag-"+fileName);
|
||||
|
||||
String mime = mimeTypes.getMimeByExtension(fileName);
|
||||
if (mime == null)
|
||||
|
|
Loading…
Reference in New Issue