My basic goal is to serve the following clean URLs with nginx:
- /serves- /index.html
- /abc/serves- /abc/index.html
- /abc/defserves- /abc/def.html
- /abcredirects 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.htmlredirects to- /
- /abc/index.htmlredirects to- /abc/
- /abc/def.htmlredirects 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:
- /,- /indexand- /index.htmlall redirect to- /(loop).
- /abcand- /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.

