package io.dropwizard.jetty;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.Iterables;
import io.dropwizard.util.Size;
import org.eclipse.jetty.server.Handler;

import javax.annotation.Nullable;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.Deflater;

import static java.util.Objects.requireNonNull;

Builds GZIP filters.

Configuration Parameters:
Name Default Description
enabled true If true, all requests with `gzip` or `deflate` in the `Accept-Encoding` header will have their response entities compressed and requests with `gzip` or `deflate` in the `Content-Encoding` header will have their request entities decompressed.
minimumEntitySize 256 bytes All response entities under this size are not compressed.
bufferSize 8KiB The size of the buffer to use when compressing.
excludedUserAgentPatterns (none) The set of user agent patterns to exclude from compression.
compressedMimeTypes (Jetty's default) The list of mime types to compress. The default is all types apart the commonly known image, video, audio and compressed types.
includedMethods (Jetty's default) The list list of HTTP methods to compress. The default is to compress only GET responses.
deflateCompressionLevel -1 The compression level used for ZLIB deflation(compression).
gzipCompatibleInflation true If true, then ZLIB inflation(decompression) will be performed in the GZIP-compatible mode.
/** * Builds GZIP filters. * * <p/> * <b>Configuration Parameters:</b> * <table> * <tr> * <td>Name</td> * <td>Default</td> * <td>Description</td> * </tr> * <tr> * <td>{@code enabled}</td> * <td>true</td> * <td>If true, all requests with `gzip` or `deflate` in the `Accept-Encoding` header will have their * response entities compressed and requests with `gzip` or `deflate` in the `Content-Encoding` * header will have their request entities decompressed.</td> * </tr> * <tr> * <td>{@code minimumEntitySize}</td> * <td>256 bytes</td> * <td>All response entities under this size are not compressed.</td> * </tr> * <tr> * <td>{@code bufferSize}</td> * <td>8KiB</td> * <td>The size of the buffer to use when compressing.</td> * </tr> * <tr> * <td>{@code excludedUserAgentPatterns}</td> * <td>(none)</td> * <td>The set of user agent patterns to exclude from compression. </td> * </tr> * <tr> * <td>{@code compressedMimeTypes}</td> * <td>(Jetty's default)</td> * <td>The list of mime types to compress. The default is all types apart the * commonly known image, video, audio and compressed types.</td> * </tr> * <tr> * <td>{@code includedMethods}</td> * <td>(Jetty's default)</td> * <td>The list list of HTTP methods to compress. The default is to compress * only GET responses.</td> * </tr> * <tr> * <td>{@code deflateCompressionLevel}</td> * <td>-1</td> * <td>The compression level used for ZLIB deflation(compression).</td> * </tr> * <tr> * <td>{@code gzipCompatibleInflation}</td> * <td>true</td> * <td>If true, then ZLIB inflation(decompression) will be performed in the GZIP-compatible mode.</td> * </tr> * </table> */
public class GzipHandlerFactory { private boolean enabled = true; @NotNull private Size minimumEntitySize = Size.bytes(256); @NotNull private Size bufferSize = Size.kilobytes(8); // By default compress responses for all user-agents private Set<String> excludedUserAgentPatterns = new HashSet<>(); @Nullable private Set<String> compressedMimeTypes; @Nullable private Set<String> includedMethods; @Min(Deflater.DEFAULT_COMPRESSION) @Max(Deflater.BEST_COMPRESSION) private int deflateCompressionLevel = Deflater.DEFAULT_COMPRESSION; private boolean gzipCompatibleInflation = true; private boolean syncFlush = false; @JsonProperty public boolean isEnabled() { return enabled; } @JsonProperty public void setEnabled(boolean enabled) { this.enabled = enabled; } @JsonProperty public Size getMinimumEntitySize() { return minimumEntitySize; } @JsonProperty public void setMinimumEntitySize(Size size) { this.minimumEntitySize = requireNonNull(size); } @JsonProperty public Size getBufferSize() { return bufferSize; } @JsonProperty public void setBufferSize(Size size) { this.bufferSize = requireNonNull(size); } @JsonProperty @Nullable public Set<String> getCompressedMimeTypes() { return compressedMimeTypes; } @JsonProperty public void setCompressedMimeTypes(Set<String> mimeTypes) { this.compressedMimeTypes = mimeTypes; } @JsonProperty public int getDeflateCompressionLevel() { return deflateCompressionLevel; } @JsonProperty public void setDeflateCompressionLevel(int level) { this.deflateCompressionLevel = level; } @JsonProperty public boolean isGzipCompatibleInflation() { return gzipCompatibleInflation; } @JsonProperty public void setGzipCompatibleInflation(boolean gzipCompatibleInflation) { this.gzipCompatibleInflation = gzipCompatibleInflation; } public Set<String> getExcludedUserAgentPatterns() { return excludedUserAgentPatterns; } public void setExcludedUserAgentPatterns(Set<String> excludedUserAgentPatterns) { this.excludedUserAgentPatterns = excludedUserAgentPatterns; } @JsonProperty @Nullable public Set<String> getIncludedMethods() { return includedMethods; } @JsonProperty public void setIncludedMethods(Set<String> methods) { this.includedMethods = methods; } @JsonProperty public boolean isSyncFlush() { return syncFlush; } @JsonProperty public void setSyncFlush(boolean syncFlush) { this.syncFlush = syncFlush; } public BiDiGzipHandler build(@Nullable Handler handler) { final BiDiGzipHandler gzipHandler = new BiDiGzipHandler(); gzipHandler.setHandler(handler); gzipHandler.setMinGzipSize((int) minimumEntitySize.toBytes()); gzipHandler.setInputBufferSize((int) bufferSize.toBytes()); gzipHandler.setCompressionLevel(deflateCompressionLevel); gzipHandler.setSyncFlush(syncFlush); if (compressedMimeTypes != null) { gzipHandler.setIncludedMimeTypes(Iterables.toArray(compressedMimeTypes, String.class)); } if (includedMethods != null) { gzipHandler.setIncludedMethods(Iterables.toArray(includedMethods, String.class)); } gzipHandler.setExcludedAgentPatterns(Iterables.toArray(excludedUserAgentPatterns, String.class)); gzipHandler.setInflateNoWrap(gzipCompatibleInflation); return gzipHandler; } }