Merge remote-tracking branch 'origin/jetty-9.4.x'

This commit is contained in:
Greg Wilkins 2016-06-08 16:25:29 +10:00
commit 3fafd6ee8f
3 changed files with 122 additions and 16 deletions

View File

@ -30,6 +30,7 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.CompressedContentFormat; import org.eclipse.jetty.http.CompressedContentFormat;
import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.HttpVersion;
@ -478,6 +479,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
int i=etag.indexOf(CompressedContentFormat.GZIP._etagQuote); int i=etag.indexOf(CompressedContentFormat.GZIP._etagQuote);
if (i>0) if (i>0)
{ {
baseRequest.setAttribute("o.e.j.s.h.gzip.GzipHandler.etag",etag);
while (i>=0) while (i>=0)
{ {
etag=etag.substring(0,i)+etag.substring(i+CompressedContentFormat.GZIP._etag.length()); etag=etag.substring(0,i)+etag.substring(i+CompressedContentFormat.GZIP._etag.length());

View File

@ -158,6 +158,19 @@ public class GzipHttpOutputInterceptor implements HttpOutput.Interceptor
{ {
LOG.debug("{} exclude by status {}",this,sc); LOG.debug("{} exclude by status {}",this,sc);
noCompression(); noCompression();
if (sc==304)
{
String request_etags = (String)_channel.getRequest().getAttribute("o.e.j.s.h.gzip.GzipHandler.etag");
String response_etag = response.getHttpFields().get(HttpHeader.ETAG);
if (request_etags!=null && response_etag!=null)
{
String response_etag_gzip=etagGzip(response_etag);
if (request_etags.contains(response_etag_gzip))
response.getHttpFields().put(HttpHeader.ETAG,response_etag_gzip);
}
}
_interceptor.write(content, complete, callback); _interceptor.write(content, complete, callback);
return; return;
} }
@ -217,11 +230,7 @@ public class GzipHttpOutputInterceptor implements HttpOutput.Interceptor
response.setContentLength(-1); response.setContentLength(-1);
String etag=fields.get(HttpHeader.ETAG); String etag=fields.get(HttpHeader.ETAG);
if (etag!=null) if (etag!=null)
{ fields.put(HttpHeader.ETAG,etagGzip(etag));
int end = etag.length()-1;
etag=(etag.charAt(end)=='"')?etag.substring(0,end)+ GZIP._etag+'"':etag+GZIP._etag;
fields.put(HttpHeader.ETAG,etag);
}
LOG.debug("{} compressing {}",this,_deflater); LOG.debug("{} compressing {}",this,_deflater);
_state.set(GZState.COMPRESSING); _state.set(GZState.COMPRESSING);
@ -232,6 +241,12 @@ public class GzipHttpOutputInterceptor implements HttpOutput.Interceptor
callback.failed(new WritePendingException()); callback.failed(new WritePendingException());
} }
private String etagGzip(String etag)
{
int end = etag.length()-1;
return (etag.charAt(end)=='"')?etag.substring(0,end)+ GZIP._etag+'"':etag+GZIP._etag;
}
public void noCompression() public void noCompression()
{ {
while (true) while (true)

View File

@ -19,10 +19,14 @@
package org.eclipse.jetty.servlet; package org.eclipse.jetty.servlet;
import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalToIgnoringCase;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@ -42,6 +46,7 @@ import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.gzip.GzipHandler; import org.eclipse.jetty.server.handler.gzip.GzipHandler;
import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.IO;
import org.hamcrest.Matchers;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -62,6 +67,8 @@ public class GzipHandlerTest
"Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+ "Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+
"et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque."; "et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
private static String __contentETag = String.format("W/\"%x\"",__content.hashCode());
private static String __contentETagGzip = String.format("W/\"%x--gzip\"",__content.hashCode());
private static String __icontent = "BEFORE"+__content+"AFTER"; private static String __icontent = "BEFORE"+__content+"AFTER";
private Server _server; private Server _server;
@ -75,6 +82,7 @@ public class GzipHandlerTest
_server.addConnector(_connector); _server.addConnector(_connector);
GzipHandler gzipHandler = new GzipHandler(); GzipHandler gzipHandler = new GzipHandler();
gzipHandler.setExcludedAgentPatterns();
ServletContextHandler context = new ServletContextHandler(gzipHandler,"/ctx"); ServletContextHandler context = new ServletContextHandler(gzipHandler,"/ctx");
ServletHandler servlets = context.getServletHandler(); ServletHandler servlets = context.getServletHandler();
@ -92,11 +100,18 @@ public class GzipHandlerTest
{ {
@Override @Override
protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException
{
response.setHeader("ETag",__contentETag);
String ifnm = req.getHeader("If-None-Match");
if (ifnm!=null && ifnm.equals(__contentETag))
response.sendError(304);
else
{ {
PrintWriter writer = response.getWriter(); PrintWriter writer = response.getWriter();
writer.write(__content); writer.write(__content);
} }
} }
}
public static class ForwardServlet extends HttpServlet public static class ForwardServlet extends HttpServlet
{ {
@ -125,6 +140,33 @@ public class GzipHandlerTest
_server.join(); _server.join();
} }
@Test
public void testNotGzipHandler() throws Exception
{
// generated and parsed test
HttpTester.Request request = HttpTester.newRequest();
HttpTester.Response response;
request.setMethod("GET");
request.setURI("/ctx/content");
request.setVersion("HTTP/1.0");
request.setHeader("Host","tester");
response = HttpTester.parseResponse(_connector.getResponses(request.generate()));
assertThat(response.getStatus(),is(200));
assertThat(response.get("Content-Encoding"),not(equalToIgnoringCase("gzip")));
assertThat(response.get("ETag"),is(__contentETag));
assertThat(response.get("Vary"),is("Accept-Encoding"));
InputStream testIn = new ByteArrayInputStream(response.getContentBytes());
ByteArrayOutputStream testOut = new ByteArrayOutputStream();
IO.copy(testIn,testOut);
assertEquals(__content, testOut.toString("UTF8"));
}
@Test @Test
public void testGzipHandler() throws Exception public void testGzipHandler() throws Exception
{ {
@ -133,22 +175,65 @@ public class GzipHandlerTest
HttpTester.Response response; HttpTester.Response response;
request.setMethod("GET"); request.setMethod("GET");
request.setURI("/ctx/content");
request.setVersion("HTTP/1.0"); request.setVersion("HTTP/1.0");
request.setHeader("Host","tester"); request.setHeader("Host","tester");
request.setHeader("accept-encoding","gzip"); request.setHeader("accept-encoding","gzip");
request.setURI("/ctx/content");
response = HttpTester.parseResponse(_connector.getResponses(request.generate())); response = HttpTester.parseResponse(_connector.getResponses(request.generate()));
assertTrue(response.get("Content-Encoding").equalsIgnoreCase("gzip")); assertThat(response.getStatus(),is(200));
assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertThat(response.get("Content-Encoding"),Matchers.equalToIgnoringCase("gzip"));
assertThat(response.get("ETag"),is(__contentETagGzip));
assertThat(response.get("Vary"),is("Accept-Encoding"));
InputStream testIn = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes())); InputStream testIn = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes()));
ByteArrayOutputStream testOut = new ByteArrayOutputStream(); ByteArrayOutputStream testOut = new ByteArrayOutputStream();
IO.copy(testIn,testOut); IO.copy(testIn,testOut);
assertEquals(__content, testOut.toString("UTF8")); assertEquals(__content, testOut.toString("UTF8"));
}
@Test
public void testETagNotGzipHandler() throws Exception
{
// generated and parsed test
HttpTester.Request request = HttpTester.newRequest();
HttpTester.Response response;
request.setMethod("GET");
request.setURI("/ctx/content");
request.setVersion("HTTP/1.0");
request.setHeader("Host","tester");
request.setHeader("If-None-Match",__contentETag);
request.setHeader("accept-encoding","gzip");
response = HttpTester.parseResponse(_connector.getResponses(request.generate()));
assertThat(response.getStatus(),is(304));
assertThat(response.get("Content-Encoding"),not(Matchers.equalToIgnoringCase("gzip")));
assertThat(response.get("ETag"),is(__contentETag));
}
@Test
public void testETagGzipHandler() throws Exception
{
// generated and parsed test
HttpTester.Request request = HttpTester.newRequest();
HttpTester.Response response;
request.setMethod("GET");
request.setURI("/ctx/content");
request.setVersion("HTTP/1.0");
request.setHeader("Host","tester");
request.setHeader("If-None-Match",__contentETagGzip);
request.setHeader("accept-encoding","gzip");
response = HttpTester.parseResponse(_connector.getResponses(request.generate()));
assertThat(response.getStatus(),is(304));
assertThat(response.get("Content-Encoding"),not(Matchers.equalToIgnoringCase("gzip")));
assertThat(response.get("ETag"),is(__contentETagGzip));
} }
@Test @Test
@ -166,8 +251,10 @@ public class GzipHandlerTest
response = HttpTester.parseResponse(_connector.getResponses(request.generate())); response = HttpTester.parseResponse(_connector.getResponses(request.generate()));
assertTrue(response.get("Content-Encoding").equalsIgnoreCase("gzip")); assertThat(response.getStatus(),is(200));
assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertThat(response.get("Content-Encoding"),Matchers.equalToIgnoringCase("gzip"));
assertThat(response.get("ETag"),is(__contentETagGzip));
assertThat(response.get("Vary"),is("Accept-Encoding"));
InputStream testIn = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes())); InputStream testIn = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes()));
ByteArrayOutputStream testOut = new ByteArrayOutputStream(); ByteArrayOutputStream testOut = new ByteArrayOutputStream();
@ -191,8 +278,10 @@ public class GzipHandlerTest
response = HttpTester.parseResponse(_connector.getResponses(request.generate())); response = HttpTester.parseResponse(_connector.getResponses(request.generate()));
assertTrue(response.get("Content-Encoding").equalsIgnoreCase("gzip")); assertThat(response.getStatus(),is(200));
assertEquals(HttpServletResponse.SC_OK,response.getStatus()); assertThat(response.get("Content-Encoding"),Matchers.equalToIgnoringCase("gzip"));
assertThat(response.get("ETag"),nullValue());
assertThat(response.get("Vary"),is("Accept-Encoding"));
InputStream testIn = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes())); InputStream testIn = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes()));
ByteArrayOutputStream testOut = new ByteArrayOutputStream(); ByteArrayOutputStream testOut = new ByteArrayOutputStream();