My basic goal is to serve the following clean URLs with nginx:
/
serves/index.html
/abc/
serves/abc/index.html
/abc/def
serves/abc/def.html
/abc
redirects to/abc/
In order to have canonical names for each resource, I also want to normalize any URL with superfluous file names or extensions:
/index.html
redirects to/
/abc/index.html
redirects to/abc/
/abc/def.html
redirects to/abc/def
The directives I thought would accomplish this:
index index.html;
try_files $uri.html $uri $uri/ =404;
# Redirect */index and */index.html to *.
rewrite ^(.*)/index(\.html)?$ $1 permanent;
# Redirect *.html to *.
rewrite ^(.+)\.html$ $1 permanent;
However, the result of this is different than I expected:
/
,/index
and/index.html
all redirect to/
(loop)./abc
and/abc/
both redirect to/abc/
(loop).
(It works as designed for /abc/def.html
and /abc/def
; only the directory URLs don't work.)
I'm not sure what is happening here; maybe I'm misunderstanding how the rewrite
works?
(I already tried using location blocks instead, but this also results in loops as try_files
performs an internal redirect to the location block that sends the HTTP 301.)
Edit: Fundamentally, I need something like a location block that only matches the original request URI, but is ignored for the purpose of internal redirects, so it doesn't create a loop in combination with the try_files directive.
Best Answer
You might be looking for a solution like the one explained here: