If I understand correctly it's better not to gzip small resources as they might actually get bigger while still having a performance hit on the CPU. So using the gzip_min_length directive is an obvious solution to that. However, when trying this on a server that runs a REST API I'm working on this doesn't seem to work. When I receive an empty json response, or a very small one, the Content-Encoding header is still present and reading "gzip".
My question is why this setting is not being respected by NginX and what can I do to fix it?
The API is built on the Lumen microframework.
I have attached the Gzip setting I'm using in my nginx.conf:
# Compression
# Enable Gzip compressed.
gzip on;
# Enable compression both for HTTP/1.0 and HTTP/1.1.
gzip_http_version 1.1;
# Compression level (1-9).
# 5 is a perfect compromise between size and cpu usage, offering about
# 75% reduction for most ascii files (almost identical to level 9).
gzip_comp_level 5;
# Don't compress anything that's already small and unlikely to shrink much
# if at all (the default is 20 bytes, which is bad as that usually leads to
# larger files after gzipping).
gzip_min_length 1000;
# Compress data even for clients that are connecting to us via proxies,
# identified by the "Via" header (required for CloudFront).
gzip_proxied any;
# Tell proxies to cache both the gzipped and regular version of a resource
# whenever the client's Accept-Encoding capabilities header varies;
# Avoids the issue where a non-gzip capable client (which is extremely rare
# today) would display gibberish if their proxy gave them the gzipped version.
gzip_vary on;
# Compress all output labeled with one of the following MIME-types.
gzip_types
application/atom+xml
application/javascript
application/json
application/rss+xml
application/vnd.ms-fontobject
application/x-font-ttf
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/svg+xml
image/x-icon
text/css
text/plain
text/x-component;
# text/html is always compressed by HttpGzipModule
Confirming my note above, this does seem to correspond to the note in the NGINX gzip module documentation stating "The length is determined only from the “Content-Length” response header field."
With gzip_min_length 1000;
, my JSON responses were being gzip'ed, even if they were only 100 bytes.
I changed my application to add the Content-Length: 100
header and NGINX sends the JSON response without using the gzip encoding.
If I change the configuration to gzip_min_length 80;
with the same 100-byte Content-Length, then NGINX applies the gzip encoding as expected.
Short story: you need to apply the Content-Length
header for NGINX to properly handle the gzip_min_length
check.