Opened 12 years ago

Closed 12 years ago

Last modified 11 years ago

#261 closed defect (fixed)

HEAD requests still have content-type when gzip on

Reported by: Stephen Dendtler Owned by: Valentin V. Bartenev
Priority: minor Milestone:
Component: nginx-module Version: 1.3.x
Keywords: gzip Cc:
uname -a: Linux - 2.6.32-71.el6.x86_64 #1 SMP Fri May 20 03:51:51 BST 2011 x86_64 x86_64 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.3.9
TLS SNI support enabled
configure arguments: --prefix=/usr/local/PACKAGES/nginx-1.3.9 --with-poll_module --with-http_ssl_module --with-http_flv_module --with-openssl=/usr/local/PKG_BUILD/openssl-0.9.8r --with-pcre=/usr/local/PKG_BUILD/pcre-8.12 --add-module=nginx_uploadprogress_module --with-syslog --add-module=ngx_cache_purge-1.3 --with-file-aio --with-ld-opt=-ldl --add-module=nginx-sticky-module-1.1


When using proxy_pass for HEAD requests, combined with gzip being turned on, nginx is returning body content even when the backend returns no content. This is a bug as no content is supposed to be returned in a HEAD response.

We're consistently seeing 20 bytes of binary data being sent after the HEAD response headers in a separate packet, possibly corresponding to a gzip header for 0 bytes of content.

This seems to be confusing some proxies such as Apache when keepalives are enabled where it sends a HEAD request followed by a GET request. Apache is accepting the content returned on the HEAD request without applying un-gzip methods, and prepending it to the content returned by the GET request as it's part of the same TCP stream. While this is arguably a problem in Apache, if nginx's output conformed to the HTTP spec then this wouldn't be an issue.

Temporary workaround is to add this to the corresponding location definition:

if ($request_method = HEAD ) {

gzip off;


Sample gzip config:

gzip on;
gzip_min_length 1000;
gzip_buffers 12 32k;
gzip_http_version 1.0;
gzip_comp_level 6;
gzip_proxied any;
gzip_vary off;
gzip_types text/plain text/html text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
gzip_disable "MSIE [1-6].(?!.*SV1)";

Sample request to replicate the issue:

Accept-Encoding: gzip, deflate
Connection: Keep-Alive

Headers from the upstream server will be returned (expected), along with 20 bytes of binary data (bug).

Change History (6)

comment:1 by Valentin V. Bartenev, 12 years ago

Status: newaccepted

comment:2 by Valentin V. Bartenev, 12 years ago

This patch should fix the problem:

  • src/http/modules/ngx_http_gzip_filter_module.c

    diff -r 8e06d02d06f2 src/http/modules/ngx_http_gzip_filter_module.c
    a b ngx_http_gzip_header_filter(ngx_http_req  
    251251            && r->headers_out.content_encoding->value.len)
    252252        || (r->headers_out.content_length_n != -1
    253253            && r->headers_out.content_length_n < conf->min_length)
    254         || ngx_http_test_content_type(r, &conf->types) == NULL
    255         || r->header_only)
     254        || ngx_http_test_content_type(r, &conf->types) == NULL)
    256255    {
    257256        return ngx_http_next_header_filter(r);
    258257    }
    319318    ngx_chain_t          *cl;
    320319    ngx_http_gzip_ctx_t  *ctx;
     321    if (r->header_only) {
     322        return ngx_http_next_body_filter(r, in);
     323    }
    322325    ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module);
    324327    if (ctx == NULL || ctx->done) {

comment:3 by maxim, 12 years ago

Owner: set to Valentin V. Bartenev
Status: acceptedassigned

comment:4 by Valentin V. Bartenev, 12 years ago

Resolution: fixed
Status: assignedclosed

In 4991/nginx:

(The changeset message doesn't reference this ticket)

comment:5 by Valentin V. Bartenev, 12 years ago

A better fix was commited as r4991. Thanks for the report.

comment:6 by Maxim Dounin, 11 years ago

In 5055/nginx:

(The changeset message doesn't reference this ticket)

Note: See TracTickets for help on using tickets.