Opened 7 years ago

Closed 7 years ago

Last modified 6 years ago

#1367 closed defect (invalid)

`gzip_static always` doesn't use index.html.gz unless index.html exists

Reported by: foolip@… Owned by:
Priority: minor Milestone:
Component: other Version: 1.10.x
Keywords: Cc:
uname -a: Linux bgsound 4.9.0-3-amd64 #1 SMP Debian 4.9.30-2+deb9u2 (2017-06-26) x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.10.3
built with OpenSSL 1.1.0f 25 May 2017
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-2tpxfc/nginx-1.10.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module --add-dynamic-module=/build/nginx-2tpxfc/nginx-1.10.3/debian/modules/nginx-auth-pam --add-dynamic-module=/build/nginx-2tpxfc/nginx-1.10.3/debian/modules/nginx-dav-ext-module --add-dynamic-module=/build/nginx-2tpxfc/nginx-1.10.3/debian/modules/nginx-echo --add-dynamic-module=/build/nginx-2tpxfc/nginx-1.10.3/debian/modules/nginx-upstream-fair --add-dynamic-module=/build/nginx-2tpxfc/nginx-1.10.3/debian/modules/ngx_http_substitutions_filter_module

Description

My config:

server {
  listen 443 ssl http2 default_server;
  ssl_certificate /etc/letsencrypt/live/html.foolip.org/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/html.foolip.org/privkey.pem;

  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";

  server_name html.foolip.org;

  root /var/www/html.foolip.org;

  gzip_static always;
}

(This might not match what's currently on html.foolip.org.)

With this config, if /var/www/html.foolip.org/index.html.gz exists but index.html does not, https://html.foolip.org/ is 403 forbidden. Creating an empty index.html makes it work, serving the content from index.html.gz and ignoring the content of index.html, as expected with the gzip_static always config.

Note that the problem does not apply when requesting https://html.foolip.org/index.html or something like https://html.foolip.org/foo.html if only foo.html.gz exists on disk.

Just a guess, but the fact that https://html.foolip.org/ is 403 instead of 404 is significant, perhaps gzip_static hooks into a "file not found" phase that's different from what happens if no index file is found. Note that adding "index index.html" to the config doesn't change this.

Change History (4)

comment:1 by Maxim Dounin, 7 years ago

Resolution: invalid
Status: newclosed

The problem is that requests to / are first handled by the index module, and 403 is be returned as there are no index file. The gzip_static module only works when returning a particular file, and no file is returned in this case. See How nginx processes a request for an introduction on request processing in nginx.

For the gzip_static module to work you have to somehow instruct nginx that a request to / should return /index.html. Normally this is done by index module due to an index file, and most trivial solution would be to create an empty index.html as you did in your tests. Alternatively, you can configure rewrite to change requests from / to /index.html.

comment:2 by Maxim Dounin, 6 years ago

See also #1620, #1621, #1622.

in reply to:  1 ; comment:3 by zijung@…, 6 years ago

Replying to mdounin:

The problem is that requests to / are first handled by the index module, and 403 is be returned as there are no index file. The gzip_static module only works when returning a particular file, and no file is returned in this case. See How nginx processes a request for an introduction on request processing in nginx.

For the gzip_static module to work you have to somehow instruct nginx that a request to / should return /index.html. Normally this is done by index module due to an index file, and most trivial solution would be to create an empty index.html as you did in your tests. Alternatively, you can configure rewrite to change requests from / to /index.html.

But even if index.html exists, index.html.gz will not be used.
The module returns NGX_DECLINED if the last character of URI is '/'.
This is a part of the module source (line 102):

if (r->uri.data[r->uri.len - 1] == '/') {
    return NGX_DECLINED;
}

in reply to:  3 comment:4 by Maxim Dounin, 6 years ago

Replying to zijung@…:

But even if index.html exists, index.html.gz will not be used.

This is not true. You can try it yourself to find out.

The module returns NGX_DECLINED if the last character of URI is '/'.

Please refer to How nginx processes a request to better understand how nginx works.

Note: See TracTickets for help on using tickets.