nginx: gzip on server is lost during proxy

Using nginx as a reverse proxy/load balancer in front of iis/.NET application servers.

Our servers are configured to gzip response payloads. Works fine.

When we stick gzip in front, responses are no longer gzipped.

Question 1: We need to reconfigure gzip in nginx?

Question 2: Is it appropriate to be doing the gzip work twice?

  • nginx passes request to web server
  • web server gzips response
  • (I think) nginx unzips response, re-gzips response

What is the right thing to do here?

(I feel like gzip should happen only at one layer, though there is a benefit of reducing load on the wire, even behind nginx.)

Here is my current config params for gzip (in http section, before first upstream block)

# ******************************  begin gzip section ********************
# Compression 
gzip on;     # Enable Gzip compressed.

# 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.
# text/html is always compressed by HttpGzipModule
gzip_types
    text/css
    text/*
    text/javascript
    message/*
    application/x-javascript
    application/json
    application/xml
    application/atom+xml
    application/xaml+xml;
# ******************************  end gzip section ********************

Solution 1:

This is likely due to the HTTP version that IIS is running gzip on.

The Nginx proxy makes backend requests by default over HTTP 1.0. Most browsers at this point use HTTP 1.1.

I'm not sure about IIS, but nginx runs gzip on HTTP 1.1.

So without the proxy in the middle, the request is probably getting to the backend over HTTP 1.1. With the proxy in the middle, the request is hitting the backend on HTTP 1.0.

Try setting proxy_http_version 1.1 on your proxy server. This will send backend requests over HTTP 1.1.

You should only gzip once. In general it's best to do it at the actual app (like you are doing) so that the gzipped response can be cached by downstream caching layers etc. The app developer should be making the determination as to whether or not gzip would be beneficial (based on the size of the response, whether it is compressible, etc). So I'd recommend turning gzip off on your proxy.