tjmc
tjmc

Reputation: 148

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 documentation describing the modrewrite for nginx ?

Upvotes: 11

Views: 36347

Answers (7)

Nicolas Wu
Nicolas Wu

Reputation: 4985

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.

Upvotes: 8

mgutt
mgutt

Reputation: 6177

This one works:

# redirect dumb search engines
location /index.html {
    if ($request_uri = /index.html) {
        rewrite ^ $scheme://$host? permanent;
    }
}

Upvotes: 2

barryp
barryp

Reputation: 126

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;

Upvotes: 1

Jackson Ray Hamilton
Jackson Ray Hamilton

Reputation: 9466

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;
}

Upvotes: 8

Abid Mujtaba
Abid Mujtaba

Reputation: 1

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;

    ... }

Upvotes: 0

Hendrik
Hendrik

Reputation: 4929

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;
}

Upvotes: 2

Evgeny Zislis
Evgeny Zislis

Reputation: 6957

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/;
}

Upvotes: 3

Related Questions