version: 2.1.6.RELEASE my configuration
server:
compression:
enabled: true
min-response-size: 50MB
my understanding is that it compresses when the threshold is exceeded, but it compresses me no matter how much I adjust the threshold.How to use it(min-response-size)
Comment From: snicoll
@zhaoyunxing92 there are a number of tests in Spring Boot that assert the response is not compressed if the min size isn't reached. It's hard to know where the problem is with the information you've provided. Please share a minimal sample (github repo or zip we can download) that reproduces the problem you are describing.
Comment From: zhaoyunxing92
github
access in the browser :http://127.0.0.1:8080/
Compression turned off was 2.6kb of data,if open 463b,then set min-response-size: 50MB,Is still 463b,I feel like it's not working
Comment From: snicoll
Thanks for the sample. This works as expected with Webflux and Netty. I can see we have some code that configures tomcat and it's invoked properly so I am wondering why there is a Content-Encoding there.
Paging @bclozel
Comment From: wilkinsona
This is Tomcat's standard behaviour. It only honours the minimum response size for compression when the response size is known:
https://github.com/apache/tomcat/blob/6b125eb8df2074bad094d0a8f090a59f0d6a692b/java/org/apache/coyote/CompressionConfig.java#L200-L204
// Check if the response is of sufficient length to trigger the compression
long contentLength = response.getContentLengthLong();
if (contentLength != -1 && contentLength < compressionMinSize) {
return false;
}
In the above -1 indicates that the response's content length in unknown.
When working with JSON, for the response size to be known you would have to buffer the response in memory and then write it out. That can be achieved with a Filter and a ContentCachingResponseWrapper but I would not recommend it, particularly if your application returns large amounts of JSON.
Comment From: martin-lindboe
@wilkinsona, I have done something similar, and it can be done using the standard buffer in the servlet response (ServletResponse.setBufferSize) as long as the min content size is reasonable (2-16 KB). The default output buffer size in Tomcat is 8 KB, so you are unlikely to allocate a lot more memory with this approach. The overhead comes from counting the bytes written to the buffer.
In our implementation, if the min response size is reasonably small, we request that as the buffer size (ServletResponse.setBufferSize), then wrap the servlet response to wrap the stream to count the number of bytes written. (We can get the min content size with the Value annotation - using the same default value as the Compression class.)
After delegating to the filter chain, if the response has not been committed, set the content length (ServletResponse.setContentLength) to the number of bytes written before returning from the filter.
As with all solutions, there are limits too its applicability, but I would recommend this for the standard use cases (e.g. Sprint Boot MVC services).
I agree it is not a bug or a defect, and it is not hard to work around. The code was quickly written, but I did spend some time scratching my head first and it is nice not to have to worry about Tomcat implementation details.