nginxurl-rewritingclean-url

Nginx rewrite to make a "personal URL"


I'd like to be able to make "personal URL" for our users (Facebook like), which is of course a dynamic strings. it needs to be in the root of the site, and that is why I'm having a big headache with it.

The requirements that I have are:

1. I need www.example.com/John.Doe (it can be a-zA-Z0-9_-.)

and rewrite it to:

www.example.com/profile?id=John.Doe

2. I also need the site scripts to be extension less like (which I was able to do, with the great people here, using "$uri.php$is_args$query_string;"):

so www.example.com/login will go to: www.example.com/login.php

I tried a lot of things, but I just can't get the right formula to make it work. This is my configuration, right now:

location / {
     try_files $uri $uri/ $uri.php$is_args$query_string;
}

location ~ \.php$ {
    if ($request_uri ~ ^/([^?]*)\.php(\?.*)?$) {
         return 301 /$1$2;
    }
    try_files $uri =404;
    include /etc/nginx/fastcgi_params;
    fastcgi_pass  127.0.0.1:9001;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

Solution

  • You have an overlapping namespace for your extension-less scripts and your personal URLs, so you need to test for the presence of the $uri.php file before rewriting it to profile.php.

    So rather than rewrite the URI in the first try_files directive (as you have it now), it may be better to use a named location block to process the PHP file without having to rewrite it first.

    Like this:

    location / {
        try_files $uri $uri/ @php;
    }
    
    location @php {
        try_files $uri.php @rewrite;
    
        include /etc/nginx/fastcgi_params;
        fastcgi_pass  127.0.0.1:9001;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
    
    location @rewrite {
        rewrite ^/([a-zA-Z0-9_.-]+)$ /profile.php?id=$1 last;
    }
    
    location ~ \.php$ {
        if ($request_uri ...) { ... }
    
        try_files $uri =404;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass  127.0.0.1:9001;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
    

    The first block serves static files. The second block processes extension-less PHP files (if and only if they exists). The third block performs a rewrite to profile.php (which does not need to be extension-less, as it is not exposed to the client). The fourth block processes normal .php URIs and includes your $request_uri fix.

    Note that fastcgi_index is redundant in both this and the original configuration.

    For more details, here are some links to the nginx documentation for the location, try_files and rewrite directives.