mirror of
https://github.com/jetty/jetty.project.git
synced 2025-03-04 04:49:12 +00:00
Merge pull request #7873 from eclipse/jetty-10.0.x-4414-gzipInflationExclusion
Issue #4414 - add option to exclude paths from GzipHandler request inflation
This commit is contained in:
commit
7a5ea2bac0
@ -168,6 +168,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||||||
// non-static, as other GzipHandler instances may have different configurations
|
// non-static, as other GzipHandler instances may have different configurations
|
||||||
private final IncludeExclude<String> _methods = new IncludeExclude<>();
|
private final IncludeExclude<String> _methods = new IncludeExclude<>();
|
||||||
private final IncludeExclude<String> _paths = new IncludeExclude<>(PathSpecSet.class);
|
private final IncludeExclude<String> _paths = new IncludeExclude<>(PathSpecSet.class);
|
||||||
|
private final IncludeExclude<String> _inflatePaths = new IncludeExclude<>(PathSpecSet.class);
|
||||||
private final IncludeExclude<String> _mimeTypes = new IncludeExclude<>(AsciiLowerCaseSet.class);
|
private final IncludeExclude<String> _mimeTypes = new IncludeExclude<>(AsciiLowerCaseSet.class);
|
||||||
private HttpField _vary = GzipHttpOutputInterceptor.VARY_ACCEPT_ENCODING;
|
private HttpField _vary = GzipHttpOutputInterceptor.VARY_ACCEPT_ENCODING;
|
||||||
|
|
||||||
@ -354,6 +355,41 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds excluded Path Specs for request filtering on request inflation.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* There are 2 syntaxes supported, Servlet <code>url-pattern</code> based, and
|
||||||
|
* Regex based. This means that the initial characters on the path spec
|
||||||
|
* line are very strict, and determine the behavior of the path matching.
|
||||||
|
* <ul>
|
||||||
|
* <li>If the spec starts with <code>'^'</code> the spec is assumed to be
|
||||||
|
* a regex based path spec and will match with normal Java regex rules.</li>
|
||||||
|
* <li>If the spec starts with <code>'/'</code> then spec is assumed to be
|
||||||
|
* a Servlet url-pattern rules path spec for either an exact match
|
||||||
|
* or prefix based match.</li>
|
||||||
|
* <li>If the spec starts with <code>'*.'</code> then spec is assumed to be
|
||||||
|
* a Servlet url-pattern rules path spec for a suffix based match.</li>
|
||||||
|
* <li>All other syntaxes are unsupported</li>
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* Note: inclusion takes precedence over exclude.
|
||||||
|
*
|
||||||
|
* @param pathspecs Path specs (as per servlet spec) to exclude. If a
|
||||||
|
* ServletContext is available, the paths are relative to the context path,
|
||||||
|
* otherwise they are absolute.<br>
|
||||||
|
* For backward compatibility the pathspecs may be comma separated strings, but this
|
||||||
|
* will not be supported in future versions.
|
||||||
|
* @see #addIncludedInflationPaths(String...)
|
||||||
|
*/
|
||||||
|
public void addExcludedInflationPaths(String... pathspecs)
|
||||||
|
{
|
||||||
|
for (String p : pathspecs)
|
||||||
|
{
|
||||||
|
_inflatePaths.exclude(StringUtil.csvSplit(p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds included HTTP Methods (eg: POST, PATCH, DELETE) for filtering.
|
* Adds included HTTP Methods (eg: POST, PATCH, DELETE) for filtering.
|
||||||
*
|
*
|
||||||
@ -440,6 +476,38 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add included Path Specs for filtering on request inflation.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* There are 2 syntaxes supported, Servlet <code>url-pattern</code> based, and
|
||||||
|
* Regex based. This means that the initial characters on the path spec
|
||||||
|
* line are very strict, and determine the behavior of the path matching.
|
||||||
|
* <ul>
|
||||||
|
* <li>If the spec starts with <code>'^'</code> the spec is assumed to be
|
||||||
|
* a regex based path spec and will match with normal Java regex rules.</li>
|
||||||
|
* <li>If the spec starts with <code>'/'</code> then spec is assumed to be
|
||||||
|
* a Servlet url-pattern rules path spec for either an exact match
|
||||||
|
* or prefix based match.</li>
|
||||||
|
* <li>If the spec starts with <code>'*.'</code> then spec is assumed to be
|
||||||
|
* a Servlet url-pattern rules path spec for a suffix based match.</li>
|
||||||
|
* <li>All other syntaxes are unsupported</li>
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
|
* Note: inclusion takes precedence over exclusion.
|
||||||
|
*
|
||||||
|
* @param pathspecs Path specs (as per servlet spec) to include. If a
|
||||||
|
* ServletContext is available, the paths are relative to the context path,
|
||||||
|
* otherwise they are absolute
|
||||||
|
*/
|
||||||
|
public void addIncludedInflationPaths(String... pathspecs)
|
||||||
|
{
|
||||||
|
for (String p : pathspecs)
|
||||||
|
{
|
||||||
|
_inflatePaths.include(StringUtil.csvSplit(p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DeflaterPool.Entry getDeflaterEntry(Request request, long contentLength)
|
public DeflaterPool.Entry getDeflaterEntry(Request request, long contentLength)
|
||||||
{
|
{
|
||||||
@ -495,6 +563,18 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||||||
return excluded.toArray(new String[0]);
|
return excluded.toArray(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current filter list of excluded Path Specs for request inflation.
|
||||||
|
*
|
||||||
|
* @return the filter list of excluded Path Specs
|
||||||
|
* @see #getIncludedInflationPaths()
|
||||||
|
*/
|
||||||
|
public String[] getExcludedInflationPaths()
|
||||||
|
{
|
||||||
|
Set<String> excluded = _inflatePaths.getExcluded();
|
||||||
|
return excluded.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current filter list of included HTTP Methods
|
* Get the current filter list of included HTTP Methods
|
||||||
*
|
*
|
||||||
@ -531,6 +611,18 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||||||
return includes.toArray(new String[0]);
|
return includes.toArray(new String[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current filter list of included Path Specs for request inflation.
|
||||||
|
*
|
||||||
|
* @return the filter list of included Path Specs
|
||||||
|
* @see #getExcludedInflationPaths()
|
||||||
|
*/
|
||||||
|
public String[] getIncludedInflationPaths()
|
||||||
|
{
|
||||||
|
Set<String> includes = _inflatePaths.getIncluded();
|
||||||
|
return includes.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the minimum size, in bytes, that a response {@code Content-Length} must be
|
* Get the minimum size, in bytes, that a response {@code Content-Length} must be
|
||||||
* before compression will trigger.
|
* before compression will trigger.
|
||||||
@ -585,7 +677,7 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||||||
|
|
||||||
// Handle request inflation
|
// Handle request inflation
|
||||||
HttpFields httpFields = baseRequest.getHttpFields();
|
HttpFields httpFields = baseRequest.getHttpFields();
|
||||||
boolean inflated = _inflateBufferSize > 0 && httpFields.contains(HttpHeader.CONTENT_ENCODING, "gzip");
|
boolean inflated = _inflateBufferSize > 0 && httpFields.contains(HttpHeader.CONTENT_ENCODING, "gzip") && isPathInflatable(path);
|
||||||
if (inflated)
|
if (inflated)
|
||||||
{
|
{
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
@ -750,6 +842,20 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||||||
return _paths.test(requestURI);
|
return _paths.test(requestURI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if the provided Request URI is allowed to be inflated based on the Path Specs filters.
|
||||||
|
*
|
||||||
|
* @param requestURI the request uri
|
||||||
|
* @return whether decompressing is allowed for the given the path.
|
||||||
|
*/
|
||||||
|
protected boolean isPathInflatable(String requestURI)
|
||||||
|
{
|
||||||
|
if (requestURI == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return _inflatePaths.test(requestURI);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the excluded filter list of HTTP methods (replacing any previously set)
|
* Set the excluded filter list of HTTP methods (replacing any previously set)
|
||||||
*
|
*
|
||||||
@ -799,6 +905,20 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||||||
_paths.exclude(pathspecs);
|
_paths.exclude(pathspecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the excluded filter list of Path specs (replacing any previously set)
|
||||||
|
*
|
||||||
|
* @param pathspecs Path specs (as per servlet spec) to exclude from inflation. If a
|
||||||
|
* ServletContext is available, the paths are relative to the context path,
|
||||||
|
* otherwise they are absolute.
|
||||||
|
* @see #setIncludedInflatePaths(String...)
|
||||||
|
*/
|
||||||
|
public void setExcludedInflatePaths(String... pathspecs)
|
||||||
|
{
|
||||||
|
_inflatePaths.getExcluded().clear();
|
||||||
|
_inflatePaths.exclude(pathspecs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set of supported {@link DispatcherType} that this filter will operate on.
|
* Set of supported {@link DispatcherType} that this filter will operate on.
|
||||||
*
|
*
|
||||||
@ -861,6 +981,20 @@ public class GzipHandler extends HandlerWrapper implements GzipFactory
|
|||||||
_paths.include(pathspecs);
|
_paths.include(pathspecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the included filter list of Path specs (replacing any previously set)
|
||||||
|
*
|
||||||
|
* @param pathspecs Path specs (as per servlet spec) to include for inflation. If a
|
||||||
|
* ServletContext is available, the paths are relative to the context path,
|
||||||
|
* otherwise they are absolute
|
||||||
|
* @see #setExcludedInflatePaths(String...)
|
||||||
|
*/
|
||||||
|
public void setIncludedInflatePaths(String... pathspecs)
|
||||||
|
{
|
||||||
|
_inflatePaths.getIncluded().clear();
|
||||||
|
_inflatePaths.include(pathspecs);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the minimum response size to trigger dynamic compression.
|
* Set the minimum response size to trigger dynamic compression.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -40,6 +40,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.eclipse.jetty.http.CompressedContentFormat;
|
import org.eclipse.jetty.http.CompressedContentFormat;
|
||||||
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
import org.eclipse.jetty.http.HttpTester;
|
import org.eclipse.jetty.http.HttpTester;
|
||||||
import org.eclipse.jetty.server.HttpOutput;
|
import org.eclipse.jetty.server.HttpOutput;
|
||||||
import org.eclipse.jetty.server.LocalConnector;
|
import org.eclipse.jetty.server.LocalConnector;
|
||||||
@ -55,6 +56,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.contains;
|
import static org.hamcrest.Matchers.contains;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.hamcrest.Matchers.equalToIgnoringCase;
|
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.not;
|
||||||
@ -688,6 +690,49 @@ public class GzipHandlerTest
|
|||||||
assertEquals(__icontent, testOut.toString("UTF8"));
|
assertEquals(__icontent, testOut.toString("UTF8"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIncludeExcludeGzipHandlerInflate() throws Exception
|
||||||
|
{
|
||||||
|
gzipHandler.addExcludedInflationPaths("/ctx/echo/exclude");
|
||||||
|
gzipHandler.addIncludedInflationPaths("/ctx/echo/include");
|
||||||
|
|
||||||
|
String message = "hello world";
|
||||||
|
byte[] gzippedMessage = gzipContent(message);
|
||||||
|
|
||||||
|
// The included path does deflate the content.
|
||||||
|
HttpTester.Response response = sendGzipRequest("/ctx/echo/include", message);
|
||||||
|
assertThat(response.getStatus(), equalTo(HttpStatus.OK_200));
|
||||||
|
assertThat(response.getContent(), equalTo(message));
|
||||||
|
|
||||||
|
// The excluded path does not deflate the content.
|
||||||
|
response = sendGzipRequest("/ctx/echo/exclude", message);
|
||||||
|
assertThat(response.getStatus(), equalTo(HttpStatus.OK_200));
|
||||||
|
assertThat(response.getContentBytes(), equalTo(gzippedMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] gzipContent(String content) throws IOException
|
||||||
|
{
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
GZIPOutputStream output = new GZIPOutputStream(baos);
|
||||||
|
output.write(content.getBytes(StandardCharsets.UTF_8));
|
||||||
|
output.close();
|
||||||
|
return baos.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpTester.Response sendGzipRequest(String uri, String data) throws Exception
|
||||||
|
{
|
||||||
|
HttpTester.Request request = HttpTester.newRequest();
|
||||||
|
request.setMethod("GET");
|
||||||
|
request.setURI(uri);
|
||||||
|
request.setVersion("HTTP/1.0");
|
||||||
|
request.setHeader("Host", "tester");
|
||||||
|
request.setHeader("Content-Type", "text/plain");
|
||||||
|
request.setHeader("Content-Encoding", "gzip");
|
||||||
|
request.setContent(gzipContent(data));
|
||||||
|
|
||||||
|
return HttpTester.parseResponse(_connector.getResponse(request.generate()));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddGetPaths()
|
public void testAddGetPaths()
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user