64

I want my nginx make display all url's clean.

With some research I've made the first case to work. It`s done by following configuration:

location / {
    root   html;
    index  index.html index.htm index.php;
    try_files $uri.html $uri/ =404; 
}

It works for indexhtml.html displaying as indexhtml, but nothing happens with .php. If I change $uri.html to $uri.php, it works neither for .html, neither .php. I`ve tried to put something similar in php location but without any success.

Any advices?

2
  • 1
    hold on, do you want the extension to be added without the dot ? Commented Feb 20, 2014 at 17:58
  • No, I do not need extension at all. Thats only for example to understand, that Im not an weirdo, whos having both index.php and index.html files on my server. However, its already solved. Commented Feb 20, 2014 at 18:40

5 Answers 5

69

From what I've researched, if you append your /etc/nginx/conf.d/domain.tld.conf file to include:

location / {
    try_files $uri $uri.html $uri/ @extensionless-php;
    index index.html index.htm index.php;
}

location ~ \.php$ {
    try_files $uri =404;
}

location @extensionless-php {
    rewrite ^(.*)$ $1.php last;
}

Then restart nginx and give it a go. Hopefully this will help you! More information can be found (where I found it) here @ tweaktalk.net

Sign up to request clarification or add additional context in comments.

5 Comments

Funny. If I delete codetry_files $uri.html $uri/ =404;code from my previous configuration and add Yours, than everything works fine with php, but doesn`t work with html. If I do not remove previous line and add Yours, "Problem loading page" shows up. How can I combine them to work both?
Try changing your 'try_files' line under 'location' to: try_files $uri $uri.html $uri/ @extensionless-php; Or possibly: try_files $uri $uri.html $uri/ @extensionless-php $uri/ =404;
Thanks a lot! I replaced try_files $uri $uri/ @extensionless-php; with try_files $uri.html $uri/ @extensionless-php; and it`s finally working both for html and php. Great!
Incase you have installed nginx on Windows n cant seem to find "/etc/nginx/conf.d/domain.tld", then this is actually the same as "nginx/conf/nginx.conf"
Use this to your ddns server.
64

No need for extra blocks and named locations and everything. Also move the index line outside the location block

server {
  index index.html index.php;
  location / {
    try_files $uri $uri/ $uri.html $uri.php$is_args$query_string;
  }
  location ~ \.php$ {
    try_files $uri =404;
    # add fastcgi_pass line here, depending if you use socket or port
  }
}

Keep in mind that if you have a folder and a file with the same name inside the same folder, like /folder/xyz/ and /folder/xyz.php you won't be able to run the php file if the folder xyz contains an index.php or index.html, just keep this in mind.

3 Comments

@elbowlobstercowstand, just another addition, when using $query_string, I prefer using $is_args instead of a plain ? would be a tiny bit cleaner when there's no actual args by not having a trailing ? in the url.
Just to add, the important bit in making this work is the =404 needs to be in the try_files in the .php block, not at the end of the location / one, otherwise you'll get 404 errors for URLs for which a .php file does exists.
@elbowlobstercowstand was right, I rolled back his last edit, nginx will not see the _GET array if ?$query_string was not added.
14

To further Mohammad's answer, you might also want to offer redirects from .html and .php to the extensionless versions.

This can be accomplished due to the fact that $request_uri contains "full original request URI (with arguments)", and is not affected by the internal rewrites that are not visible to the user.

server {
  index index.html index.php;
  location / {
    if ($request_uri ~ ^/(.*)\.html$) {  return 302 /$1;  }
    try_files $uri $uri/ $uri.html $uri.php?$args;
  }
  location ~ \.php$ {
    if ($request_uri ~ ^/([^?]*)\.php($|\?)) {  return 302 /$1?$args;  }
    try_files $uri =404;
    # add fastcgi_pass line here, depending if you use socket or port
  }
}

6 Comments

"Directive if has problems when used in location context, in some cases it doesn’t do what you expect but something completely different instead. In some cases it even segfaults. It’s generally a good idea to avoid it if possible." nginx.com/resources/wiki/start/topics/depth/ifisevil
@Tag, sounds like there should be a separate page ifisevilisevil; it you actually read the ifisevil document you've linked, you'll note that doing a return from within if is explicitly advertised as always being 100% safe, and that's exactly what i'm doing in my answer
It may be safe, but it isn't the best practice. Please read Pitfalls and Common Mistakes.
@Tag, since when is using a safe if is not the best practice? Also, why are you linking to a page that doesn't even claim that it's not the best practice, yet act as if it does claim that it's not?
It can be done without IF: stackoverflow.com/questions/31502521/…
|
5

This has worked for me for more than 5 years going.

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

}

Comments

2

Perhaps this may be of use for you... It' Simple and gets the job done:

location / {
  rewrite ^/([^\.]+)$ /$1.html break;
}

1 Comment

it worked, but now php is not being processed...the php was downloaded!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.