Spring Boot Topic

Spring Boot Enable HTTP Compression

HTTP compression is a technique that reduces the size of HTTP responses, resulting in faster page load times, reduced bandwidth usage, and improved user experience. Spring Boot makes it easy to enable and configure HTTP compression.

What is HTTP Compression?

HTTP compression works by:

  • Compressing response bodies before sending them to clients

  • Using algorithms like GZIP or Deflate

  • Reducing file sizes typically by 60-80%

  • Automatically handling compression/decompression via HTTP headers

Enabling HTTP Compression in Spring Boot

1. Basic Configuration

Spring Boot enables HTTP compression through simple configuration properties in application.properties or application.yml:

application.properties:

# Enable HTTP compression
server.compression.enabled=true

# Minimum response size to trigger compression (default: 2048 bytes)
server.compression.min-response-size=1024

# MIME types that should be compressed
server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json,application/xml

# Compression level (0-9, where 0=no compression, 9=maximum compression)
server.compression.level=6

application.yml:

server:
  compression:
    enabled: true
    min-response-size: 1024
    mime-types: 
      - text/html
      - text/xml
      - text/plain
      - text/css
      - text/javascript
      - application/javascript
      - application/json
      - application/xml
    level: 6

2. Advanced Configuration

For more granular control, you can configure compression programmatically:

@Configuration
public class CompressionConfig {

    @Bean
    public FilterRegistrationBean<CompressingFilter> compressionFilter() {
        FilterRegistrationBean<CompressingFilter> registrationBean = 
            new FilterRegistrationBean<>();
        
        CompressingFilter compressingFilter = new CompressingFilter();
        
        // Configure compression settings
        registrationBean.setFilter(compressingFilter);
        registrationBean.addUrlPatterns("/*");
        
        // Set initialization parameters
        registrationBean.addInitParameter("compressionThreshold", "1024");
        registrationBean.addInitParameter("compressedContentTypes", 
            "text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json");
        
        return registrationBean;
    }
}

How HTTP Compression Works

1. Request-Response Flow

Client Request:
GET /api/data HTTP/1.1
Host: example.com
Accept-Encoding: gzip, deflate  ← Client indicates compression support

Server Response:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Encoding: gzip          ← Server indicates compressed content
Content-Length: 1500

[Compressed JSON data...]

2. Compression Process

// Simplified internal Spring Boot process
public class CompressionProcess {
    
    public void handleResponse(HttpServletResponse response, byte[] content) {
        // Check if compression should be applied
        if (shouldCompress(response, content)) {
            
            // Apply GZIP compression
            ByteArrayOutputStream compressed = new ByteArrayOutputStream();
            try (GZIPOutputStream gzip = new GZIPOutputStream(compressed)) {
                gzip.write(content);
            }
            
            byte[] compressedData = compressed.toByteArray();
            
            // Set appropriate headers
            response.setHeader("Content-Encoding", "gzip");
            response.setContentLength(compressedData.length);
            
            // Write compressed data
            response.getOutputStream().write(compressedData);
        } else {
            // Write uncompressed data
            response.getOutputStream().write(content);
        }
    }
    
    private boolean shouldCompress(HttpServletResponse response, byte[] content) {
        return content.length >= minResponseSize &&
               isCompressibleContentType(response.getContentType()) &&
               clientSupportsCompression(request);
    }
}

Configuration Parameters Explained

1. Compression Levels

Level Compression Speed Use Case
0 No compression Fastest Development
1 Minimal Very Fast Real-time applications
6 Balanced Balanced General web applications
9 Maximum Slowest Static content delivery

2. MIME Type Considerations

Highly compressible:

  • Text-based content (HTML, CSS, JS, JSON, XML)

  • Compression ratio: 60-80%

Less compressible:

  • Already compressed formats (JPEG, PNG, PDF, ZIP)

  • Compression ratio: 0-10% (may even increase size)

3. Response Size Threshold

  • Small files: Below threshold may not benefit from compression

  • Large files: Significant bandwidth savings

  • Default: 2048 bytes (optimal balance for most applications)

Custom Compression Configuration

1. Custom Compression Filter

@Component
public class CustomCompressionFilter implements Filter {
    
    private static final String[] COMPRESSIBLE_TYPES = {
        "text/html", "text/xml", "text/plain", "text/css", 
        "text/javascript", "application/javascript", "application/json"
    };
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, 
                        FilterChain chain) throws IOException, ServletException {
        
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        
        if (supportsCompression(httpRequest)) {
            CompressedResponseWrapper wrappedResponse = 
                new CompressedResponseWrapper(httpResponse);
            chain.doFilter(request, wrappedResponse);
            wrappedResponse.finishResponse();
        } else {
            chain.doFilter(request, response);
        }
    }
    
    private boolean supportsCompression(HttpServletRequest request) {
        String acceptEncoding = request.getHeader("Accept-Encoding");
        return acceptEncoding != null && 
               (acceptEncoding.contains("gzip") || acceptEncoding.contains("deflate"));
    }
}

2. Response Wrapper for Compression

public class CompressedResponseWrapper extends HttpServletResponseWrapper {
    private GZIPServletOutputStream gzipStream;
    private PrintWriter writer;
    private boolean compressionEnabled = false;
    
    public CompressedResponseWrapper(HttpServletResponse response) {
        super(response);
    }
    
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        if (writer != null) {
            throw new IllegalStateException("getWriter() has already been called");
        }
        
        if (gzipStream == null) {
            gzipStream = new GZIPServletOutputStream(super.getOutputStream());
            compressionEnabled = true;
        }
        return gzipStream;
    }
    
    public void finishResponse() throws IOException {
        if (writer != null) {
            writer.close();
        } else if (gzipStream != null) {
            gzipStream.close();
        }
    }
}

Testing Compression

1. Using curl to Test

# Test without compression
curl -H "Accept-Encoding: identity" http://localhost:8080/api/data

# Test with GZIP compression
curl -H "Accept-Encoding: gzip" --compressed http://localhost:8080/api/data

# Check response headers
curl -I -H "Accept-Encoding: gzip" http://localhost:8080/api/data

2. Unit Testing

@SpringBootTest
class CompressionTest {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    void testResponseIsCompressed() {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Accept-Encoding", "gzip");
        
        HttpEntity<String> entity = new HttpEntity<>(headers);
        
        ResponseEntity<String> response = restTemplate.exchange(
            "/api/data", HttpMethod.GET, entity, String.class);
        
        // Verify compression headers
        assertThat(response.getHeaders().getContentEncoding()).isEqualTo("gzip");
    }
}

Performance Considerations

1. CPU vs Bandwidth Trade-off

// Performance impact analysis
public class CompressionPerformance {
    
    // Compression reduces bandwidth but increases CPU usage
    public void analyzeTradeoff() {
        // Small files: Compression overhead may outweigh benefits
        // Large files: Significant bandwidth savings
        // Text content: High compression ratio
        // Binary content: Low compression ratio
    }
}

2. Recommended Settings by Use Case

Web Application:

server.compression.enabled=true
server.compression.min-response-size=1024
server.compression.level=6

API Service:

server.compression.enabled=true
server.compression.min-response-size=512  # API responses are often smaller
server.compression.mime-types=application/json
server.compression.level=4

Static Content Server:

server.compression.enabled=true
server.compression.min-response-size=2048
server.compression.level=9  # Maximum compression for static files

Common Issues and Solutions

1. Compression Not Working

Check:

  • Client sends Accept-Encoding header

  • Response size exceeds minimum threshold

  • Content type is in compressible types list

  • No other filters interfere with compression

2. Performance Problems

Solutions:

  • Reduce compression level for CPU-intensive applications

  • Increase minimum response size threshold

  • Exclude already-compressed content types

3. Browser Compatibility

Most modern browsers support GZIP and Deflate compression automatically. Ensure your configuration includes:

server.compression.mime-types=text/html,text/css,text/javascript,application/javascript,application/json,application/xml,text/xml,text/plain

Best Practices

  1. Enable compression for all production environments

  2. Use appropriate compression levels based on your use case

  3. Monitor CPU usage if serving high traffic

  4. Test with real data to find optimal settings

  5. Exclude already compressed formats (images, PDFs, etc.)

  6. Consider CDN compression for static assets

HTTP compression in Spring Boot is a powerful feature that significantly improves application performance with minimal configuration effort.

 

Comments (0)

No comments yet. Be the first to comment!

LecturreAI Assistant

Hello! I'm LecturreAI

What would you like to learn today?