Gzip compression is a technique used to reduce the size of HTTP responses by compressing them before sending them over the network. Learn to enable HTTP response gzip compression in a Spring Boot application.
By default, the Gzip compression is disabled in Spring Boot.
1. Enable Gzip Compression “Globally”
1.1. Properties Configuration
The following response compression-related Spring Boot properties are applicable to Jetty, Tomcat, and Undertow. Define these properties in the application.properties file.
server.compression.enabled=true
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain
server.compression.min-response-size=1024
server.compression.excluded-user-agents=MSIE 6.0,UCBrowser
A similar configuration can be written in YAML as follows:
server:
compression:
enabled: true
mime-types: application/json,application/xml,text/html,text/xml,text/plain
min-response-size: 1024
excluded-user-agents: MSIE 6.0,UCBrowser
- server.compression.enabled enables or disables the compression.
- server.compression.min-response-size – configures the minimum number of bytes in response for compression to be performed. The default size is
2048
bytes. - server.compression.mime-types – enables compression only if their content type is one of the given mime-types.
- server.compression.excluded-user-agents – specifies a comma-separated list of user-agent patterns for which Gzip compression should be excluded.
1.2. Wildcards in Mime-types are not Supported
The compression in Spring Boot relies on support provided by underlying embedded servers. Unfortunately, these servers do not provide any consistent wildcard support in mime-type.
1.2.1. Jetty
Jetty performs strict string comparisons when determining whether to compress a response based on MIME type. Wildcards such as *
are not supported directly for matching multiple MIME types. [Link]
However, Jetty provides an alternative mechanism for configuring a whitelist or blacklist of MIME types explicitly. This allows you to specify which MIME types should or should not be compressed.
For example, you might configure a whitelist to explicitly list the MIME types that should be compressed:
server.compression.mime-types=application/json,application/xml,text/html
1.2.2. Tomcat
While Tatomc doesn’t support wildcards in the traditional sense, you can configure MIME types in a way that covers a range of similar types. [Link]
So configuring ‘application/vnd.company‘ would work for both ‘application/vnd.company.v3+json‘ and ‘application/vnd.company.v2+xml‘.
server.compression.mime-types=application/json,application/xml,application/vnd.company
2. Enable Gzip Compression for Specific URLs Only
The default compression (using properties) is applied to all responses sent from the server. If we need more control over when to apply the compression and when to skip it, we can create a custom filter.
In the following example, we create the GzipResponseCompressionFilter class, a Servlet 3.0 filter. In it’s doFilter() method, we check the URL pattern and any additional pre-checks (such as the client has requested for compressed output?), and return the gzip compressed output, if needed.
@WebFilter(urlPatterns = {"/pattern-1", "/pattern-2" , "/*"})
public class GzipResponseCompressionFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
if (acceptsGZipEncoding(httpRequest)) {
CustomHttpServletResponseWrapper gzipResponse = new CustomHttpServletResponseWrapper(httpResponse);
gzipResponse.setHeader("Content-Encoding", "gzip");
chain.doFilter(request, gzipResponse);
gzipResponse.close();
} else {
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
}
private boolean acceptsGZipEncoding(HttpServletRequest request) {
String acceptEncoding = request.getHeader("Accept-Encoding");
return acceptEncoding != null && acceptEncoding.contains("gzip");
}
}
The CustomHttpServletResponseWrapper and CustomServletOutputStream classes handle the actual compression and wrap the uncompressed response into a compressed one.
class CustomHttpServletResponseWrapper extends HttpServletResponseWrapper {
private GZIPOutputStream gzipOutputStream;
private ServletOutputStream outputStream;
private PrintWriter writer;
public CustomHttpServletResponseWrapper(HttpServletResponse response) throws IOException {
super(response);
this.gzipOutputStream = new GZIPOutputStream(response.getOutputStream());
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
if (this.outputStream == null) {
this.outputStream = new CustomServletOutputStream(this.gzipOutputStream);
}
return this.outputStream;
}
@Override
public PrintWriter getWriter() throws IOException {
if (this.writer == null) {
this.writer = new PrintWriter(new OutputStreamWriter(this.gzipOutputStream, getCharacterEncoding()));
}
return this.writer;
}
@Override
public void flushBuffer() throws IOException {
if (this.writer != null) {
this.writer.flush();
}
if (this.outputStream != null) {
this.outputStream.flush();
}
this.gzipOutputStream.flush();
}
public void close() throws IOException {
this.gzipOutputStream.close();
}
}
class CustomServletOutputStream extends ServletOutputStream {
private final GZIPOutputStream gzipOutputStream;
public CustomServletOutputStream(GZIPOutputStream gzipOutputStream) {
this.gzipOutputStream = gzipOutputStream;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setWriteListener(WriteListener writeListener) {
}
@Override
public void write(int b) throws IOException {
this.gzipOutputStream.write(b);
}
}
Finally, use the @ServletComponentScan annotation to automatically scan and configure the filter class with Spring boot.
@SpringBootApplication
@ServletComponentScan
public class App {
//...
}
3. Testing the Gzip Compression
Once the compression is enabled and configured, the Spring Boot application will automatically compress responses that match the configured MIME types and are larger than the specified minimum response size.
We can use tools like cURL, Postman, or browser developer tools to inspect the HTTP headers of the responses to confirm that Gzip compression is applied.
curl -X GET http://localhost:8080/api/some-endpoint -H "Accept: application/json" -I
Look for the Content-Encoding: gzip
header in the response, indicating that Gzip compression was applied.
4. Conclusion
Enabling Gzip compression is a simple and effective way to optimize the performance of your Spring Boot REST API, especially when dealing with large JSON responses or other text-based content.
Drop me your questions related to Gzip compression in Spring Boot.
Happy Learning !!
Comments