Opened 6 years ago
Closed 6 years ago
#1707 closed defect (duplicate)
try_files doesn't work sometimes
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | minor | Milestone: | nginx-1.15 |
Component: | nginx-core | Version: | 1.15.x |
Keywords: | try_files | Cc: | fuweichin@… |
uname -a: | Linux qin-workstation 4.4.0-17134-Microsoft #345-Microsoft Wed Sep 19 17:47:00 PST 2018 x86_64 GNU/Linux | ||
nginx -V: |
nginx version: nginx/1.15.7
built by gcc 6.3.0 20170516 (Debian 6.3.0-18+deb9u1) built with OpenSSL 1.1.0f 25 May 2017 (running with OpenSSL 1.1.0j 20 Nov 2018) TLS SNI support enabled configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -fdebug-prefix-map=/data/builder/debuild/nginx-1.15.7/debian/debuild-base/nginx-1.15.7=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-specs=/usr/share/dpkg/no-pie-link.specs -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie' |
Description
My site uses HTML5 History state and now I need to configure nginx to support it. Nginx supports HTML5 History state with directive 'try_files' but there is a downside: 'try_files' doesn't try files according to acceptable types of a request, which may cause developers hard to find broken non-html links, e.g. a browser wants an image/css while the server may return a html. To overcome the downside, I'm trying to do some tricks.
site configuration
server { listen 80; listen 443 ssl; server_name qin-workstation.bldgos.net; ssl_certificate /etc/ssl/certs/bldgos.net.cer; ssl_certificate_key /etc/ssl/private/bldgos.net.key; location / { root /var/www/html; index index.html; set $fallback_file $uri/; if ($http_accept ~ text/html) { set $fallback_file /index.html; } add_header Try-Files "$uri $fallback_file" always; # just to debug try_files $uri $fallback_file; } }
server root (ls /var/www/html)
index.html
request headers
GET /new-state HTTP/1.1 Host: qin-workstation.bldgos.net Connection: keep-alive Pragma: no-cache Cache-Control: no-cache Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
response headers
HTTP/1.1 404 Not Found Server: nginx/1.15.7 Date: Thu, 10 Jan 2019 09:37:38 GMT Content-Type: text/html Content-Length: 555 Connection: keep-alive Try-Files: /new-state /index.html
the problem
Now that try_files: $uri $fallback_file
is equivalent try_files: /new-state /index.html
for the request, why nginx returns 404 and not to try file '/index.html'?
my workaround to the problem
set $fallback_file /index.html; if ($uri ~ "\.(js|css|png|jpg|gif|ico)$") { set $fallback_file $uri/; } try_files $uri $fallback_file;
conclusion
Since 'try_files' can only be put into scope 'server' and 'location', but not 'if', I guess that the processing of 'try_files' may be prior to 'if'.
The
try_files
directive is not inherited into theif
block, and hence not used when theif
matches, see ticket #86, in particular this comment.Also note that using
won't work, as trailing "/" as a flag to test directory existence is only recognized directly in the
try_files
arguments, not when it comes via a variable.