try_files vs an empty location block in NGINX? - nginx

Wondering about the difference between doing:
location / {
try_files $uri $uri/ =404;
}
And doing:
location / {}
They both seem to serve files\folders only if they exist, or returning 404 error page if they don't.

There is no difference, try_files $uri $uri/ =404; is exactly the default nginx behavior:
Check if $document_root$uri is a file, and if it is, serve the request with the contents of this file;
Check if $document_root$uri is a directory, and if it is, serve the request with the first found index file from this directory. If no index files found, nginx will return directory list if you have autoindex on in your nginx config or HTTP 403 Forbidden error otherwise;
Return HTTP 404 Not found if $document_root$uri nor a file neither a directory.
Advantage of the try_files directive is that you can specify additional files/directories to check and select what to do if none of them are found (jump to another URI / jump to some named location / return any HTTP error code).
However try_files may give you some performance penalty depending of your settings, read this article by #DanilaVershinin for more details.

Related

How to deliberately block 404 error in nginx?

I have a private website for personal use only. I have no interest in anyone else accessing my webserver and want nginx to return absolutely nothing on all invalid uri.
How do I purposefully prevent 404 error (or any other errors) from being emitted for invalid uri?
Use try_files with a 'custom' fallback.
Send a 200 status on fallback if the requested file does not exists;
location / {
try_files $uri $uri/ =200;
}
try_files $uri $uri/ $uri.html =404;
The last parameter can also be a status code (directly preceded by the equals sign) or the name of a location. In the following example, a 404 error is returned if none of the parameters to the try_files directive resolve to an existing file or directory.

How do I correctly use try_files when looking in two different directories for files to serve?

I'm quite new to Nginx so I might be misunderstanding of what try_files can do.
For my local development set up I have multiple installations that will each be accesible via their own subdomain. These installations are being migrated into a new folder structure but I still want to have the ability to support both at the same time. When pulled via git the new full path looks like this :
/home/tom/git/project/v3/[installation]/public/
The old structure goes 1 directory deeper namely as follows:
/home/tom/git/project/v3/[installation]/workspace/public
Where installation is variable according to the installation name and the /public folder will be the root for nginx to work from.
The root is determined by the subdomain and is extracted via regex like so:
server_name ~^(?<subdomain>[^.]+)\.local\.project\.test;
So far I've managed to get all this working for one of the folder structures but not both at the same time. My Nginx configuration for this local domain looks like this. Below is what I've tried but just can't seem to get working. As soon as I pass the #workspace named location as fallback for try_files it always defaults to 404.
index index.html index.htm index.nginx-debian.html index.php;
server_name ~^(?<subdomain>[^.]+)\.local\.project\.test;
root /home/tom/git/project/v3/$subdomain/public/;
location / {
try_files $uri #workspace =404;
}
location #workspace {
root /home/tom/git/project/v3/$subdomain/workspace/public/;
try_files $uri =404;
}
I have also tried shortening the root and passing the following parameters to try_files
root /home/tom/git/project/v3/$subdomain;
location / {
try_files /public/$uri /workspace/public/$uri =404;
}
But this still defaults to a 404, with a $uri/ as a third parameter there it will emit a 403 forbidden trying to list the directory index of the root.
I hope someone can provide some advice or an alternative as to how to approach this issue I am facing. If I need to provide additional data let me know,
Thanks in advance.
The named location must be the last element of a try_files statement.
For example:
location / {
try_files $uri #workspace;
}
location #workspace {
...
}
See this document for details.
The $uri variable includes a leading /, so your constructed pathnames contain a // which may be why they fail.
For example:
location / {
root /home/tom/git/project/v3/$subdomain;
try_files /public$uri /workspace/public$uri =404;
}

Regular Expression to fix broken URL's in Nginx

On my previous server that ran apache I had some htaccess rules that helped forward a certain pattern of URL's which were giving 404's to the fixed pattern.
Long time ago my URLS for my site were http://domainname/articlename and then I changed it to be http://domainname/category/articlename
Now the problem is the older links that google has are returning 404's and I want to intercept any URL that doesn't have a category and insert a fake category and then my wordpress installation can resolve the URL.
So I'm looking for a nginx solution to this problem which I presume will be in the config file somewhere that will take this URL
http://www.criticalhit.net/prey/ (which gives a 404)
and change it to
http://www.criticalhit.net/fixed/prey/
which then resolves properly.
Use a named location to perform the rewrite, although this simple rewrite can be accomplished efficiently using a return 301.
Place a regular expression location (after the PHP location block) to bypass excluded URLs. This does not need to include the static files which are served by the try_files statement.
For example:
root /path/to/root;
index index.php;
location / {
try_files $uri $uri/ #rewrite;
}
location #rewrite {
return 301 /category$request_uri;
}
location ~ \.php$ {
try_files $uri =404;
...
}
location ~ ^/(category|tags|feeds) {
try_files $uri $uri/ /index.php;
}
See this document for more.

nginx with site in a subdir which does not match the ends of url

When I try to use laravel PHP framework, I try to place it in a dir called /home/usr/proj/laravel, but as we know that the public html of laravel is settled in /home/usr/proj/laravel/public, thus my problem is how to make the setting of nginx such that when I access by mysite.com/laravel/ or mysite.com/laravel, we in fact redirected to the location laravel/public/index.php.
Also, it seems that there is a rule of nignx which is suggested by the official of laravel, to make the url looks pretty
location / {
try_files $uri $uri/ /index.php?$query_string;
}
How can I use this in my case?
UPDATE
It seems the following code works for me (but give me error NotFoundHttpException in RouteCollection.php line 145:, maybe caused by my router setting)
location /laravel{
root /home/usr/proj/laravel/public;
index index.php index.html;
try_files $uri $uri/ /laravel/public/index.php?$query_string;
}
Regarding your Update, I think that you should keep your original try_files syntax:
try_files $uri $uri/ /index.php?$query_string;
since the location is set to /laravel and the root is in the public folder. The way it is currently written ends up looking for file /home/usr/proj/laravel/public/public/index.php in the disk.
You should also check to configure your application URL so that it contains the /location part of the URL. I am not quite sure about how Laravel 5 is configured since my experience is with Laravel 4.

nginx rewrite with try_files 403

I have a webserver with /usercp/ and usercp.php. I'm using tryfiles and re-write to see if file.php exists do file, otherwise goto /file/ (in my case file = usercp)
Here is my nginx conf.
location / {
try_files $uri $uri/ #extension-php;
}
location #extension-php {
rewrite ^(.*)$ $1.php last;
}
This also makes site.com/usercp/ give a 403 error. Any ideas?
The problem is that you are prioritizing the folder indexing over the php file if you want the opposite I recommend not to use the autoindex on because it exposes the contents of your folder and swap the last 2 items in the try_files, try this
location / {
try_files $uri $uri.php $uri/;
}
PS: $uri/ will always return 403 if it doesn't contain the index file specified in index because by default it forbids folder listing, you should either put the index file if that's what you intend to do, or just remove the whole $uri/ from the try_files so that it would return 404 instead of 403
http://nginx.org/r/try_files
What it does is simply checks the existence of files, and then serves the file that exists.
You claim /usercp/ exists. As such, that's what it'll try to serve. But you probably don't have autoindex on, hence, directory listing is disallowed — 403 Forbidden.

Resources