Issue #2912 Remove Content-Length from inflated requests (#2915)

Issue #2912 Remove Content-Length from inflated requests
Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
Greg Wilkins 2018-09-21 07:44:53 +10:00 committed by GitHub
parent b225ebe756
commit a9566d429c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 95 additions and 24 deletions

View File

@ -32,12 +32,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.CompressedContentFormat;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.http.*;
import org.eclipse.jetty.http.pathmap.PathSpecSet;
import org.eclipse.jetty.server.DeflaterPool;
import org.eclipse.jetty.server.HttpOutput;
@ -156,6 +151,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
public static final int DEFAULT_MIN_GZIP_SIZE=16;
private static final Logger LOG = Log.getLogger(GzipHandler.class);
private static final HttpField X_CE_GZIP = new PreEncodedHttpField("X-Content-Encoding","gzip");
private static final HttpField TE_CHUNKED = new PreEncodedHttpField(HttpHeader.TRANSFER_ENCODING, HttpHeaderValue.CHUNKED.asString());
private static final Pattern COMMA_GZIP = Pattern.compile(".*, *gzip");
private int POOL_CAPACITY = -1;
@ -622,29 +618,46 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
// Handle request inflation
if (_inflateBufferSize>0)
{
boolean inflate = false;
for (ListIterator<HttpField> i = baseRequest.getHttpFields().listIterator(); i.hasNext();)
{
HttpField field = i.next();
if (field.getHeader()!=HttpHeader.CONTENT_ENCODING)
continue;
if (field.getValue().equalsIgnoreCase("gzip"))
if (field.getHeader()==HttpHeader.CONTENT_ENCODING)
{
i.set(X_CE_GZIP);
baseRequest.getHttpInput().addInterceptor(new GzipHttpInputInterceptor(baseRequest.getHttpChannel().getByteBufferPool(),_inflateBufferSize));
break;
}
if (field.getValue().equalsIgnoreCase("gzip"))
{
i.set(X_CE_GZIP);
inflate = true;
break;
}
if (COMMA_GZIP.matcher(field.getValue()).matches())
{
String v = field.getValue();
v = v.substring(0,v.lastIndexOf(','));
i.set(new HttpField(HttpHeader.CONTENT_ENCODING,v));
i.add(X_CE_GZIP);
baseRequest.getHttpInput().addInterceptor(new GzipHttpInputInterceptor(baseRequest.getHttpChannel().getByteBufferPool(),_inflateBufferSize));
break;
if (COMMA_GZIP.matcher(field.getValue()).matches())
{
String v = field.getValue();
v = v.substring(0, v.lastIndexOf(','));
i.set(new HttpField(HttpHeader.CONTENT_ENCODING, v));
i.add(X_CE_GZIP);
inflate = true;
break;
}
}
}
}
if (inflate)
{
baseRequest.getHttpInput().addInterceptor(new GzipHttpInputInterceptor(baseRequest.getHttpChannel().getByteBufferPool(), _inflateBufferSize));
for (ListIterator<HttpField> i = baseRequest.getHttpFields().listIterator(); i.hasNext();)
{
HttpField field = i.next();
if (field.getHeader()==HttpHeader.CONTENT_LENGTH)
{
i.set(new HttpField("X-Content-Length", field.getValue()));
break;
}
}
}
}
// Are we already being gzipped?

View File

@ -35,21 +35,24 @@ import java.io.PrintWriter;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.Enumeration;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletException;
import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.gzip.GzipHandler;
import org.eclipse.jetty.util.IO;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -104,6 +107,7 @@ public class GzipHandlerTest
servlets.addServletWithMapping(IncludeServlet.class,"/include");
servlets.addServletWithMapping(EchoServlet.class,"/echo/*");
servlets.addServletWithMapping(DumpServlet.class,"/dump/*");
servlets.addFilterWithMapping(CheckFilter.class,"/*", EnumSet.of(DispatcherType.REQUEST));
_server.start();
}
@ -508,6 +512,38 @@ public class GzipHandlerTest
assertThat(response.getContent(),is(data));
}
@Test
public void testGzipRequestChunked() throws Exception
{
String data = "Hello Nice World! ";
for (int i = 0; i < 10; ++i)
data += data;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream output = new GZIPOutputStream(baos);
output.write(data.getBytes(StandardCharsets.UTF_8));
output.close();
byte[] bytes = baos.toByteArray();
// generated and parsed test
HttpTester.Request request = HttpTester.newRequest();
HttpTester.Response response;
request.setMethod("POST");
request.setURI("/ctx/echo");
request.setVersion("HTTP/1.1");
request.setHeader("Host","tester");
request.setHeader("Content-Type","text/plain");
request.setHeader("Content-Encoding","gzip");
request.add("Transfer-Encoding", "chunked");
request.setContent(bytes);
response = HttpTester.parseResponse(_connector.getResponse(request.generate()));
assertThat(response.getStatus(),is(200));
assertThat(response.getContent(),is(data));
}
@Test
@ -568,5 +604,27 @@ public class GzipHandlerTest
assertThat(response.getStatus(),is(200));
assertThat(response.getContentBytes().length,is(512*1024));
}
public static class CheckFilter implements Filter
{
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
if (request.getParameter("X-Content-Encoding")!=null)
Assert.assertEquals(-1,request.getContentLength());
else if (request.getContentLength()>=0)
Assert.assertThat(request.getParameter("X-Content-Encoding"),Matchers.nullValue());
chain.doFilter(request,response);
}
@Override
public void destroy()
{
}
}
}