org.eclipse.jetty.server.handler.gzip.GzipHandler Maven / Gradle / Ivy
Show all versions of aem-sdk-api Show documentation
//
// ========================================================================
// Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
// ------------------------------------------------------------------------
// 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.server.handler.gzip;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.ListIterator;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.zip.Deflater;
import javax.servlet.DispatcherType;
import javax.servlet.ServletContext;
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.HttpFields;
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.pathmap.PathSpecSet;
import org.eclipse.jetty.server.HttpOutput;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.IncludeExclude;
import org.eclipse.jetty.util.RegexSet;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.compression.DeflaterPool;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* A Handler that can dynamically GZIP uncompress requests, and compress responses.
*
* The GzipHandler can be applied to the entire server (a {@code gzip.mod} is included in
* the {@code jetty-home}) or it may be applied to individual contexts.
*
*
* Both Request uncompress and Response compress are gated by a configurable
* {@link DispatcherType} check on the GzipHandler.
* (This is similar in behavior to a {@link javax.servlet.Filter} configuration
* you would find in a Servlet Descriptor file ({@code WEB-INF/web.xml})
*
(Default: {@link DispatcherType#REQUEST}).
*
*
* Requests with a {@code Content-Encoding} header with the value {@code gzip} will
* be uncompressed by a {@link GzipHttpInputInterceptor} for any API that uses
* {@link HttpServletRequest#getInputStream()} or {@link HttpServletRequest#getReader()}.
*
*
* Response compression has a number of checks before GzipHandler will perform compression.
*
*
* -
* Does the request contain a {@code Accept-Encoding} header that specifies
* {@code gzip} value?
*
* -
* Is the {@link HttpServletRequest#getMethod()} allowed by the configured HTTP Method Filter.
*
(Default: {@code GET})
*
* -
* Is the incoming Path allowed by the configured Path Specs filters?
*
(Default: all paths are allowed)
*
* -
* Is the Request User-Agent allowed by the configured User-Agent filters?
*
(Default: MSIE 6 is excluded)
*
* -
* Is the Response {@code Content-Length} header present, and does its
* value meet the minimum gzip size requirements (default 32 bytes)?
*
* -
* Is the Request {@code Accept} header present and does it contain the
* required {@code gzip} value?
*
*
*
* When you encounter a configurable filter in the GzipHandler (method, paths, user-agent,
* mime-types, etc) that has both Included and Excluded values, note that the Included
* values always win over the Excluded values.
*
*
* Important note about Default Values:
* It is important to note that the GzipHandler will automatically configure itself from the
* MimeType present on the Server, System, and Contexts and the ultimate set of default values
* for the various filters (paths, methods, mime-types, etc) can be influenced by the
* available mime types to work with.
*
*
* ETag (or Entity Tag) information: any Request headers for {@code If-None-Match} or
* {@code If-Match} will be evaluated by the GzipHandler to determine if it was involved
* in compression of the response earlier. This is usually present as a {@code --gzip} suffix
* on the ETag that the Client User-Agent is tracking and handed to the Jetty server.
* The special {@code --gzip} suffix on the ETag is how GzipHandler knows that the content
* passed through itself, and this suffix will be stripped from the Request header values
* before the request is sent onwards to the specific webapp / servlet endpoint for
* handling.
* If a ETag is present in the Response headers, and GzipHandler is compressing the
* contents, it will add the {@code --gzip} suffix before the Response headers are committed
* and sent to the User Agent.
* Note that the suffix used is determined by {@link CompressedContentFormat#ETAG_SEPARATOR}
*
*
* This implementation relies on an Jetty internal {@link org.eclipse.jetty.server.HttpOutput.Interceptor}
* mechanism to allow for effective and efficient compression of the response on all Output API usages:
*
*
* -
* {@link javax.servlet.ServletOutputStream} - Obtained from {@link HttpServletResponse#getOutputStream()}
* using the traditional Blocking I/O techniques
*
* -
* {@link javax.servlet.WriteListener} - Provided to
* {@link javax.servlet.ServletOutputStream#setWriteListener(javax.servlet.WriteListener)}
* using the new (since Servlet 3.1) Async I/O techniques
*
* -
* {@link java.io.PrintWriter} - Obtained from {@link HttpServletResponse#getWriter()}
* using Blocking I/O techniques
*
*
*
* Historically the compression of responses were accomplished via
* Servlet Filters (eg: {@code GzipFilter}) and usage of {@link javax.servlet.http.HttpServletResponseWrapper}.
* Since the introduction of Async I/O in Servlet 3.1, this older form of Gzip support
* in web applications has been problematic and bug ridden.
*
*
* @deprecated The Eclipse Jetty and Apache Felix Http Jetty packages are no longer supported.
*/
@Deprecated(since = "2021-05-27")
public class GzipHandler extends HandlerWrapper implements GzipFactory {
public static final String GZIP_HANDLER_ETAGS = "o.e.j.s.h.gzip.GzipHandler.etag";
public static final String GZIP = "gzip";
public static final String DEFLATE = "deflate";
public static final int DEFAULT_MIN_GZIP_SIZE = 32;
public static final int BREAK_EVEN_GZIP_SIZE = 23;
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 Pattern COMMA_GZIP = Pattern.compile(".*, *gzip");
private int _poolCapacity = -1;
private DeflaterPool _deflaterPool = null;
private int _minGzipSize = DEFAULT_MIN_GZIP_SIZE;
private int _compressionLevel = Deflater.DEFAULT_COMPRESSION;
/**
* @deprecated feature will be removed in Jetty 10.x, with no replacement.
*/
@Deprecated
private boolean _checkGzExists = false;
private boolean _syncFlush = false;
private int _inflateBufferSize = -1;
private EnumSet _dispatchers = EnumSet.of(DispatcherType.REQUEST);
// non-static, as other GzipHandler instances may have different configurations
private final IncludeExclude _agentPatterns = new IncludeExclude<>(RegexSet.class);
private final IncludeExclude _methods = new IncludeExclude<>();
private final IncludeExclude _paths = new IncludeExclude<>(PathSpecSet.class);
private final IncludeExclude _mimeTypes = new IncludeExclude<>();
private HttpField _vary;
/**
* Instantiates a new GzipHandler.
*/
public GzipHandler() {
_methods.include(HttpMethod.GET.asString());
for (String type : MimeTypes.getKnownMimeTypes()) {
if ("image/svg+xml".equals(type))
_paths.exclude("*.svgz");
else if (type.startsWith("image/") || type.startsWith("audio/") || type.startsWith("video/"))
_mimeTypes.exclude(type);
}
_mimeTypes.exclude("application/compress");
_mimeTypes.exclude("application/zip");
_mimeTypes.exclude("application/gzip");
_mimeTypes.exclude("application/bzip2");
_mimeTypes.exclude("application/brotli");
_mimeTypes.exclude("application/x-xz");
_mimeTypes.exclude("application/x-rar-compressed");
if (LOG.isDebugEnabled())
LOG.debug("{} mime types {}", this, _mimeTypes);
_agentPatterns.exclude(".*MSIE 6.0.*");
}
/**
* Add excluded to the User-Agent filtering.
*
* @param patterns Regular expressions matching user agents to exclude
* @see #addIncludedAgentPatterns(String...)
*/
public void addExcludedAgentPatterns(String... patterns) {
_agentPatterns.exclude(patterns);
}
/**
* Add excluded to the HTTP methods filtering.
*
* @param methods The methods to exclude in compression
* @see #addIncludedMethods(String...)
*/
public void addExcludedMethods(String... methods) {
for (String m : methods) {
_methods.exclude(m);
}
}
/**
* Get the Set of {@link DispatcherType} that this Filter will operate on.
*
* @return the set of {@link DispatcherType} this filter will operate on
*/
public EnumSet getDispatcherTypes() {
return _dispatchers;
}
/**
* Set of supported {@link DispatcherType} that this filter will operate on.
*
* @param dispatchers the set of {@link DispatcherType} that this filter will operate on
*/
public void setDispatcherTypes(EnumSet dispatchers) {
_dispatchers = dispatchers;
}
/**
* Set the list of supported {@link DispatcherType} that this filter will operate on.
*
* @param dispatchers the list of {@link DispatcherType} that this filter will operate on
*/
public void setDispatcherTypes(DispatcherType... dispatchers) {
_dispatchers = EnumSet.copyOf(Arrays.asList(dispatchers));
}
/**
* Adds excluded MIME types for response filtering.
*
*
* Deprecation Warning:
* For backward compatibility the MIME types parameters may be comma separated strings,
* but this will not be supported in future versions of Jetty.
*
*
* @param types The mime types to exclude (without charset or other parameters).
* @see #addIncludedMimeTypes(String...)
*/
public void addExcludedMimeTypes(String... types) {
for (String t : types) {
_mimeTypes.exclude(StringUtil.csvSplit(t));
}
}
/**
* Adds excluded Path Specs for request filtering.
*
*
* There are 2 syntaxes supported, Servlet url-pattern
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.
*
* - If the spec starts with
'^'
the spec is assumed to be
* a regex based path spec and will match with normal Java regex rules.
* - If the spec starts with
'/'
then spec is assumed to be
* a Servlet url-pattern rules path spec for either an exact match
* or prefix based match.
* - If the spec starts with
'*.'
then spec is assumed to be
* a Servlet url-pattern rules path spec for a suffix based match.
* - All other syntaxes are unsupported
*
*
* 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.
* For backward compatibility the pathspecs may be comma separated strings, but this
* will not be supported in future versions.
* @see #addIncludedPaths(String...)
*/
public void addExcludedPaths(String... pathspecs) {
for (String p : pathspecs) {
_paths.exclude(StringUtil.csvSplit(p));
}
}
/**
* Adds included User-Agents for filtering.
*
* @param patterns Regular expressions matching user agents to include
* @see #addExcludedAgentPatterns(String...)
*/
public void addIncludedAgentPatterns(String... patterns) {
_agentPatterns.include(patterns);
}
/**
* Adds included HTTP Methods (eg: POST, PATCH, DELETE) for filtering.
*
* @param methods The HTTP methods to include in compression.
* @see #addExcludedMethods(String...)
*/
public void addIncludedMethods(String... methods) {
for (String m : methods) {
_methods.include(m);
}
}
/**
* Is the {@link Deflater} running {@link Deflater#SYNC_FLUSH} or not.
*
* @return True if {@link Deflater#SYNC_FLUSH} is used, else {@link Deflater#NO_FLUSH}
* @see #setSyncFlush(boolean)
*/
public boolean isSyncFlush() {
return _syncFlush;
}
/**
* Set the {@link Deflater} flush mode to use. {@link Deflater#SYNC_FLUSH}
* should be used if the application wishes to stream the data, but this may
* hurt compression performance.
*
* @param syncFlush True if {@link Deflater#SYNC_FLUSH} is used, else {@link Deflater#NO_FLUSH}
* @see #isSyncFlush()
*/
public void setSyncFlush(boolean syncFlush) {
_syncFlush = syncFlush;
}
/**
* Add included MIME types for response filtering
*
* @param types The mime types to include (without charset or other parameters)
* For backward compatibility the mimetypes may be comma separated strings, but this
* will not be supported in future versions.
* @see #addExcludedMimeTypes(String...)
*/
public void addIncludedMimeTypes(String... types) {
for (String t : types) {
_mimeTypes.include(StringUtil.csvSplit(t));
}
}
/**
* Add included Path Specs for filtering.
*
*
* There are 2 syntaxes supported, Servlet url-pattern
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.
*
* - If the spec starts with
'^'
the spec is assumed to be
* a regex based path spec and will match with normal Java regex rules.
* - If the spec starts with
'/'
then spec is assumed to be
* a Servlet url-pattern rules path spec for either an exact match
* or prefix based match.
* - If the spec starts with
'*.'
then spec is assumed to be
* a Servlet url-pattern rules path spec for a suffix based match.
* - All other syntaxes are unsupported
*
*
* 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 addIncludedPaths(String... pathspecs) {
for (String p : pathspecs) {
_paths.include(StringUtil.csvSplit(p));
}
}
@Override
protected void doStart() throws Exception {
_deflaterPool = newDeflaterPool(_poolCapacity);
addBean(_deflaterPool);
_vary = (_agentPatterns.size() > 0) ? GzipHttpOutputInterceptor.VARY_ACCEPT_ENCODING_USER_AGENT : GzipHttpOutputInterceptor.VARY_ACCEPT_ENCODING;
super.doStart();
}
/**
* @deprecated feature will be removed in Jetty 10.x, with no replacement.
*/
@Deprecated
public boolean getCheckGzExists() {
return _checkGzExists;
}
public int getCompressionLevel() {
return _compressionLevel;
}
@Override
public Deflater getDeflater(Request request, long contentLength) {
HttpFields httpFields = request.getHttpFields();
String ua = httpFields.get(HttpHeader.USER_AGENT);
if (ua != null && !isAgentGzipable(ua)) {
LOG.debug("{} excluded user agent {}", this, request);
return null;
}
if (contentLength >= 0 && contentLength < _minGzipSize) {
LOG.debug("{} excluded minGzipSize {}", this, request);
return null;
}
// check the accept encoding header
if (!httpFields.contains(HttpHeader.ACCEPT_ENCODING, "gzip")) {
LOG.debug("{} excluded not gzip accept {}", this, request);
return null;
}
return _deflaterPool.acquire();
}
/**
* Get the current filter list of excluded User-Agent patterns
*
* @return the filter list of excluded User-Agent patterns
* @see #getIncludedAgentPatterns()
*/
public String[] getExcludedAgentPatterns() {
Set excluded = _agentPatterns.getExcluded();
return excluded.toArray(new String[0]);
}
/**
* Get the current filter list of excluded HTTP methods
*
* @return the filter list of excluded HTTP methods
* @see #getIncludedMethods()
*/
public String[] getExcludedMethods() {
Set excluded = _methods.getExcluded();
return excluded.toArray(new String[0]);
}
/**
* Get the current filter list of excluded MIME types
*
* @return the filter list of excluded MIME types
* @see #getIncludedMimeTypes()
*/
public String[] getExcludedMimeTypes() {
Set excluded = _mimeTypes.getExcluded();
return excluded.toArray(new String[0]);
}
/**
* Get the current filter list of excluded Path Specs
*
* @return the filter list of excluded Path Specs
* @see #getIncludedPaths()
*/
public String[] getExcludedPaths() {
Set excluded = _paths.getExcluded();
return excluded.toArray(new String[0]);
}
/**
* Get the current filter list of included User-Agent patterns
*
* @return the filter list of included User-Agent patterns
* @see #getExcludedAgentPatterns()
*/
public String[] getIncludedAgentPatterns() {
Set includes = _agentPatterns.getIncluded();
return includes.toArray(new String[0]);
}
/**
* Get the current filter list of included HTTP Methods
*
* @return the filter list of included HTTP methods
* @see #getExcludedMethods()
*/
public String[] getIncludedMethods() {
Set includes = _methods.getIncluded();
return includes.toArray(new String[0]);
}
/**
* Get the current filter list of included MIME types
*
* @return the filter list of included MIME types
* @see #getExcludedMimeTypes()
*/
public String[] getIncludedMimeTypes() {
Set includes = _mimeTypes.getIncluded();
return includes.toArray(new String[0]);
}
/**
* Get the current filter list of included Path Specs
*
* @return the filter list of included Path Specs
* @see #getExcludedPaths()
*/
public String[] getIncludedPaths() {
Set includes = _paths.getIncluded();
return includes.toArray(new String[0]);
}
/**
* Get the current filter list of included HTTP methods
*
* @return the filter list of included HTTP methods
* @deprecated use {@link #getIncludedMethods()} instead. (Will be removed in Jetty 10)
*/
@Deprecated
public String[] getMethods() {
return getIncludedMethods();
}
/**
* Get the minimum size, in bytes, that a response {@code Content-Length} must be
* before compression will trigger.
*
* @return minimum response size (in bytes) that triggers compression
* @see #setMinGzipSize(int)
*/
public int getMinGzipSize() {
return _minGzipSize;
}
protected HttpField getVaryField() {
return _vary;
}
/**
* Get the size (in bytes) of the {@link java.util.zip.Inflater} buffer used to inflate
* compressed requests.
*
* @return size in bytes of the buffer, or 0 for no inflation.
*/
public int getInflateBufferSize() {
return _inflateBufferSize;
}
/**
* Set the size (in bytes) of the {@link java.util.zip.Inflater} buffer used to inflate comrpessed requests.
*
* @param size size in bytes of the buffer, or 0 for no inflation.
*/
public void setInflateBufferSize(int size) {
_inflateBufferSize = size;
}
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
ServletContext context = baseRequest.getServletContext();
String path = context == null ? baseRequest.getRequestURI() : URIUtil.addPaths(baseRequest.getServletPath(), baseRequest.getPathInfo());
LOG.debug("{} handle {} in {}", this, baseRequest, context);
if (!_dispatchers.contains(baseRequest.getDispatcherType())) {
LOG.debug("{} excluded by dispatcherType {}", this, baseRequest.getDispatcherType());
_handler.handle(target, baseRequest, request, response);
return;
}
// Handle request inflation
if (_inflateBufferSize > 0 && !baseRequest.isHandled()) {
boolean inflate = false;
for (ListIterator i = baseRequest.getHttpFields().listIterator(); i.hasNext(); ) {
HttpField field = i.next();
if (field.getHeader() == HttpHeader.CONTENT_ENCODING) {
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);
inflate = true;
break;
}
}
}
if (inflate) {
if (LOG.isDebugEnabled())
LOG.debug("{} inflate {}", this, request);
baseRequest.getHttpInput().addInterceptor(new GzipHttpInputInterceptor(baseRequest.getHttpChannel().getByteBufferPool(), _inflateBufferSize));
baseRequest.getHttpFields().computeField(HttpHeader.CONTENT_LENGTH, (header, fields) -> {
if (fields == null)
return null;
String length = fields.stream().map(HttpField::getValue).findAny().orElse("0");
return new HttpField("X-Content-Length", length);
});
}
}
// From here on out, the response output gzip determination is made
// Don't attempt to modify the response output if it's already committed.
if (response.isCommitted()) {
_handler.handle(target, baseRequest, request, response);
return;
}
// Are we already being gzipped?
HttpOutput out = baseRequest.getResponse().getHttpOutput();
HttpOutput.Interceptor interceptor = out.getInterceptor();
while (interceptor != null) {
if (interceptor instanceof GzipHttpOutputInterceptor) {
LOG.debug("{} already intercepting {}", this, request);
_handler.handle(target, baseRequest, request, response);
return;
}
interceptor = interceptor.getNextInterceptor();
}
// Special handling for etags
if (!StringUtil.isEmpty(CompressedContentFormat.ETAG_SEPARATOR)) {
for (ListIterator fields = baseRequest.getHttpFields().listIterator(); fields.hasNext(); ) {
HttpField field = fields.next();
if (field.getHeader() == HttpHeader.IF_NONE_MATCH || field.getHeader() == HttpHeader.IF_MATCH) {
String etags = field.getValue();
String etagsNoSuffix = CompressedContentFormat.GZIP.stripSuffixes(etags);
if (!etagsNoSuffix.equals(etags)) {
fields.set(new HttpField(field.getHeader(), etagsNoSuffix));
baseRequest.setAttribute(GZIP_HANDLER_ETAGS, etags);
}
}
}
}
// If not a supported method - no Vary because no matter what client, this URI is always excluded
if (!_methods.test(baseRequest.getMethod())) {
LOG.debug("{} excluded by method {}", this, request);
_handler.handle(target, baseRequest, request, response);
return;
}
// If not a supported URI- no Vary because no matter what client, this URI is always excluded
// Use pathInfo because this is be
if (!isPathGzipable(path)) {
LOG.debug("{} excluded by path {}", this, request);
_handler.handle(target, baseRequest, request, response);
return;
}
// Exclude non compressible mime-types known from URI extension. - no Vary because no matter what client, this URI is always excluded
String mimeType = context == null ? MimeTypes.getDefaultMimeByExtension(path) : context.getMimeType(path);
if (mimeType != null) {
mimeType = HttpFields.valueParameters(mimeType, null);
if (!isMimeTypeGzipable(mimeType)) {
LOG.debug("{} excluded by path suffix mime type {}", this, request);
// handle normally without setting vary header
_handler.handle(target, baseRequest, request, response);
return;
}
}
if (_checkGzExists && context != null) {
String realpath = request.getServletContext().getRealPath(path);
if (realpath != null) {
File gz = new File(realpath + ".gz");
if (gz.exists()) {
LOG.debug("{} gzip exists {}", this, request);
// allow default servlet to handle
_handler.handle(target, baseRequest, request, response);
return;
}
}
}
HttpOutput.Interceptor origInterceptor = out.getInterceptor();
try {
// install interceptor and handle
out.setInterceptor(new GzipHttpOutputInterceptor(this, getVaryField(), baseRequest.getHttpChannel(), origInterceptor, isSyncFlush()));
if (_handler != null)
_handler.handle(target, baseRequest, request, response);
} finally {
// reset interceptor if request not handled
if (!baseRequest.isHandled() && !baseRequest.isAsyncStarted())
out.setInterceptor(origInterceptor);
}
}
/**
* Test if the provided User-Agent is allowed based on the User-Agent filters.
*
* @param ua the user agent
* @return whether compressing is allowed for the given user agent
*/
protected boolean isAgentGzipable(String ua) {
if (ua == null)
return false;
return _agentPatterns.test(ua);
}
/**
* Test if the provided MIME type is allowed based on the MIME type filters.
*
* @param mimetype the MIME type to test
* @return true if allowed, false otherwise
*/
@Override
public boolean isMimeTypeGzipable(String mimetype) {
return _mimeTypes.test(mimetype);
}
/**
* Test if the provided Request URI is allowed based on the Path Specs filters.
*
* @param requestURI the request uri
* @return whether compressing is allowed for the given the path
*/
protected boolean isPathGzipable(String requestURI) {
if (requestURI == null)
return true;
return _paths.test(requestURI);
}
@Override
public void recycle(Deflater deflater) {
_deflaterPool.release(deflater);
}
/**
* Set the Check if {@code *.gz} file for the incoming file exists.
*
* @param checkGzExists whether to check if a static gz file exists for
* the resource that the DefaultServlet may serve as precompressed.
* @deprecated feature will be removed in Jetty 10.x, with no replacement.
*/
@Deprecated
public void setCheckGzExists(boolean checkGzExists) {
_checkGzExists = checkGzExists;
}
/**
* Set the Compression level that {@link Deflater} uses.
*
* @param compressionLevel The compression level to use to initialize {@link Deflater#setLevel(int)}
* @see Deflater#setLevel(int)
*/
public void setCompressionLevel(int compressionLevel) {
if (isStarted())
throw new IllegalStateException(getState());
_compressionLevel = compressionLevel;
}
/**
* Set the excluded filter list of User-Agent patterns (replacing any previously set)
*
* @param patterns Regular expressions list matching user agents to exclude
* @see #setIncludedAgentPatterns(String...)
*/
public void setExcludedAgentPatterns(String... patterns) {
_agentPatterns.getExcluded().clear();
addExcludedAgentPatterns(patterns);
}
/**
* Set the excluded filter list of HTTP methods (replacing any previously set)
*
* @param methods the HTTP methods to exclude
* @see #setIncludedMethods(String...)
*/
public void setExcludedMethods(String... methods) {
_methods.getExcluded().clear();
_methods.exclude(methods);
}
/**
* Set the excluded filter list of MIME types (replacing any previously set)
*
* @param types The mime types to exclude (without charset or other parameters)
* @see #setIncludedMimeTypes(String...)
*/
public void setExcludedMimeTypes(String... types) {
_mimeTypes.getExcluded().clear();
_mimeTypes.exclude(types);
}
/**
* Set the excluded filter list of Path specs (replacing any previously set)
*
* @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.
* @see #setIncludedPaths(String...)
*/
public void setExcludedPaths(String... pathspecs) {
_paths.getExcluded().clear();
_paths.exclude(pathspecs);
}
/**
* Set the included filter list of User-Agent patterns (replacing any previously set)
*
* @param patterns Regular expressions matching user agents to include
* @see #setExcludedAgentPatterns(String...)
*/
public void setIncludedAgentPatterns(String... patterns) {
_agentPatterns.getIncluded().clear();
addIncludedAgentPatterns(patterns);
}
/**
* Set the included filter list of HTTP methods (replacing any previously set)
*
* @param methods The methods to include in compression
* @see #setExcludedMethods(String...)
*/
public void setIncludedMethods(String... methods) {
_methods.getIncluded().clear();
_methods.include(methods);
}
/**
* Set the included filter list of MIME types (replacing any previously set)
*
* @param types The mime types to include (without charset or other parameters)
* @see #setExcludedMimeTypes(String...)
*/
public void setIncludedMimeTypes(String... types) {
_mimeTypes.getIncluded().clear();
_mimeTypes.include(types);
}
/**
* Set the included filter list of Path specs (replacing any previously set)
*
* @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
* @see #setExcludedPaths(String...)
*/
public void setIncludedPaths(String... pathspecs) {
_paths.getIncluded().clear();
_paths.include(pathspecs);
}
/**
* Set the minimum response size to trigger dynamic compression.
*
* Sizes below {@link #BREAK_EVEN_GZIP_SIZE} will result a compressed response that is larger than the
* original data.
*
*
* @param minGzipSize minimum response size in bytes (not allowed to be lower then {@link #BREAK_EVEN_GZIP_SIZE})
*/
public void setMinGzipSize(int minGzipSize) {
if (minGzipSize < BREAK_EVEN_GZIP_SIZE)
LOG.warn("minGzipSize of {} is inefficient for short content, break even is size {}", minGzipSize, BREAK_EVEN_GZIP_SIZE);
_minGzipSize = Math.max(0, minGzipSize);
}
/**
* Set the included filter list of HTTP Methods (replacing any previously set)
*
* @param csvMethods the list of methods, CSV format
* @see #setExcludedMethodList(String)
*/
public void setIncludedMethodList(String csvMethods) {
setIncludedMethods(StringUtil.csvSplit(csvMethods));
}
/**
* Get the included filter list of HTTP methods in CSV format
*
* @return the included filter list of HTTP methods in CSV format
* @see #getExcludedMethodList()
*/
public String getIncludedMethodList() {
return String.join(",", getIncludedMethods());
}
/**
* Set the excluded filter list of HTTP Methods (replacing any previously set)
*
* @param csvMethods the list of methods, CSV format
* @see #setIncludedMethodList(String)
*/
public void setExcludedMethodList(String csvMethods) {
setExcludedMethods(StringUtil.csvSplit(csvMethods));
}
/**
* Get the excluded filter list of HTTP methods in CSV format
*
* @return the excluded filter list of HTTP methods in CSV format
* @see #getIncludedMethodList()
*/
public String getExcludedMethodList() {
return String.join(",", getExcludedMethods());
}
/**
* Gets the maximum number of Deflaters that the DeflaterPool can hold.
*
* @return the Deflater pool capacity
*/
public int getDeflaterPoolCapacity() {
return _poolCapacity;
}
/**
* Sets the maximum number of Deflaters that the DeflaterPool can hold.
*/
public void setDeflaterPoolCapacity(int capacity) {
if (isStarted())
throw new IllegalStateException(getState());
_poolCapacity = capacity;
}
protected DeflaterPool newDeflaterPool(int capacity) {
return new DeflaterPool(capacity, getCompressionLevel(), true);
}
@Override
public String toString() {
return String.format("%s@%x{%s,min=%s,inflate=%s}", getClass().getSimpleName(), hashCode(), getState(), _minGzipSize, _inflateBufferSize);
}
}