nginxurl-rewritingnginx-config

Nginx: Prevent /index from being appended to the root URL with .html rewrite rule


I'm serving a static HTML site with Nginx using the following configuration:

server {
    # some configs

    # Web root and file handling
    location / {
        root /var/lib/jenkins/workspace/test;
        index index.html index.htm;
        try_files $uri $uri.html $uri/ /index.html;
    }
}

I want to remove .html from the URLs, so I added this rewrite rule:

location ~ ^/(.*)\.html$ {
    rewrite ^/(.*)\.html$ /$1 permanent;
}

This works fine for pages like /test.html, which are rewritten to /test. However, whenever I access the root URL /, the browser displays /index in the address bar, which is not what I want. I want the root URL to remain as /.

How can I prevent /index from being appended to the root URL while keeping the .html rewrite for other pages?


Solution

  • This occurs because the index nginx directive performs an internal redirect when it locates an index file, as explained in the documentation:

    It should be noted that using an index file causes an internal redirect, and the request can be processed in a different location. For example, with the following configuration:

    location = / {
        index index.html;
    }
    location / {
        ...
    }
    

    a / request will actually be processed in the second location as /index.html.

    The internal redirect from the root URL / to /index.html results in the request being processed by your regex location, which then returns an HTTP 301 redirect to the /index URL. To prevent this behavior, the simplest solution is to define a separate location specifically for the /index.html request:

    location = /index.html {
        root /var/lib/jenkins/workspace/test;
    }
    

    A more advanced solution involves modifying your regex to exclude any index.html file, regardless of its level in a nested subdirectory structure:

    location ~ ^(?<path>.*/(?!index\.html$)[^/]*)\.html$ {
        rewrite ^ $path permanent;
    }