nginx : rewrite rule to remove /index.html from the $request_uri
I've seen a few ways to rewrite the $request_uri
and add the index.html
to it when that particular file exists in the file system, like so:
if (-f $request_filename/index.html) {
rewrite (.*) $1/index.html break;
}
but i was wondering if the opposite is achievable:
i.e. when somebody requests http://example.com/index.html
, they're redirected to http://example.com
Because the nginx regexp is perl compatible, i tried something like this:
if ( $request_uri ~* "index\.html$" ) {
set $new_uri $request_uri ~* s/index\.html//
rewrite $1 permanent;
}
but it was mostly a guesswork, is there any good docume开发者_如何转开发ntation describing the modrewrite for nginx ?
I use the following rewrite in the top level server clause:
rewrite ^(.*)/index\.html$ $1 permanent;
Using this alone works for most URLs, like http://example.com/bar/index.html
, but it breaks http://example.com/index.html
. To resolve this, I have the following additional rule:
location = /index.html {
rewrite ^ / permanent;
try_files /index.html =404;
}
The =404
part returns a 404 error when the file is not found.
I have no idea why the first rewrite alone isn't sufficient.
The following config allowed me to redirect /index.html
to /
and /subdir/index.html
to /subdir/
:
# Strip "index.html" (for canonicalization)
if ( $request_uri ~ "/index.html" ) {
rewrite ^(.*)/ $1/ permanent;
}
For some reason most of the solutions mentioned here did not work. The ones that worked gave me errors with missing / in the url. This solution works for me.
Paste in your location directive.
if ( $request_uri ~ "/index.html" ) {
rewrite ^/(.*)/ /$1 permanent;
}
This one works:
# redirect dumb search engines
location /index.html {
if ($request_uri = /index.html) {
rewrite ^ $scheme://$host? permanent;
}
}
For the root /index.html
, the answer from Nicolas resulted in a redirect loop, so I had to search for other answers.
This question was asked on the nginx forums and the answer there worked better. http://forum.nginx.org/read.php?2,217899,217915
Use either
location = / {
try_files /index.html =404;
}
location = /index.html {
internal;
error_page 404 =301 $scheme://domain.com/;
}
or
location = / {
index index.html;
}
location = /index.html {
internal;
error_page 404 =301 $scheme://domain.com/;
}
This is working for me:
rewrite ^(|/(.*))/index\.html$ /$2 permanent;
It covers both the root instance /index.html
and lower instances /bar/index.html
The first part of the regex basically translates as: [nothing]
or /[something]
- in the first case $2 is an empty string so you redirect to just /
, in the second case $2 is [something]
so you redirect to /[something]
I actually went a bit fancier to cover index.html
, index.htm
, and index.php
rewrite ^(|/(.*))/index\.(html?|php)$ /$2 permanent;
The solutions quoting $scheme://domain.com/
assume that the domain is hard-coded. It was not in my case and so I used:
location / {
...
rewrite index.html $scheme://$http_host/ redirect;
... }
精彩评论