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.
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 9 months ago.
Improve this question
this nginx config is supposed to load index.php from a folder (test), and if it doesn't exist then load index.php from parent folder.
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ ^/test/(.*)$ {
try_files $uri $uri/ /test/index.php?$query_string /index.php?$query_string;
}
if I go to /test it works as expected.
but if I go to /test/something it loads index.php from root instead of the index.php from the parent folder.
Weirdly, if I remove the last /index.php?$query_string from the 2nd location block, then it actually loads the index.php from the parent folder.
So apparently the parent index is found, but for some reason nginx is deciding to look further.. Anyone know why?
Did you read the try_files directive documentation carefully? The very last parameter, if not being specified as HTTP return code or a named location name, treated as a new URI to re-evaluate from the beginning. Every other parameter treated as a file name relative to the location root. That does include every character (well, except the last slash if being specified), so nginx will check the whole $document_root/test/index.php?$query_string file existence. The ?$query_string part is not treated as an URI query string part here, but as a filename part. And even if such a file will be found, it will be served using this location content handler, which is a static one by default (unless you specified something else explicitly using the content handler declaration directive like proxy_pass, fastcgi_pass, uwsgi_pass, etc.)
The reason your PHP files gets processed with the PHP handler (usually something like location ~ \.php$ { ... }) even if your request URI doesn't include the PHP filename is either implicit redirect issued by the index directive if your try_files include the $uri/ argument (read that one documentation carefully too) or explicit redirect issued via the last /index.php?$query_string parameter of the try_files directive. Here is a quote of the most relevant index documentation part to explain this with an example:
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.
Take into attention that the regex matching locations, while having a greater priority over the prefix ones (yes, the location directive documentation is useful too), are checked in order of appearance, and the very first matched the URI will be chosen to handle the request.
Summary
Assuming your location ~ \.php$ { ... } PHP handler located above the location ~ ^/test/(.*)$ { ... }:
If your URI is /test/, it is an implicit internal redirect to /test/index.php made by index directive that makes that file to be interpreted via the PHP handler;
If your URI is /test/something and your try_files directive is try_files $uri $uri/ /test/index.php?$query_string /index.php?$query_string;, explicit internal redirect to /index.php?$query_string happens;
If your URI is /test/something and your try_files directive is try_files $uri $uri/ /test/index.php?$query_string;, explicit internal redirect to /test/index.php?$query_string happens.
If your location ~ \.php$ { ... } PHP handler will be located below the location ~ ^/test/(.*)$ { ... }:
If your URI is /test/, an implicit internal redirect by index directive to /test/index.php will took its place on the first step; on the next step you've got your /test/index.php source code in response due to the static content handler of location ~ ^/test/(.*)$ { ... };
If your URI is /test/something and your try_files directive is try_files $uri $uri/ /test/index.php?$query_string /index.php?$query_string;, explicit internal redirect to /index.php?$query_string happens;
If your URI is /test/something and your try_files directive is try_files $uri $uri/ /test/index.php?$query_string;, explicit internal to /test/index.php?$query_string happens on the first step; on the second step you've got /test/index.php source code in response by the reason already explained.
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.
My problem is connected with the next situation: when I`m trying to add a rule to remove slash from the url, I see the next error code "err_too_many_redirects"(if I try to check that such kind of links like site.com/images/ or other directory link return 403 code )
location / {
try_files $uri $uri/ /index.php?$query_string;
rewrite ^/(.*)/$ /$1 permanent;#remove slash
}
Could anyone help me to find soultion for this problem?
Site is working on nginx + php-fpm.
You have a situation where the following URL causes a 403 error, because the directory images actually exists:
example.com/images/
The problem is caused by the $uri/ element on the try_files directive attempting to locate the index for the directory.
By removing that element (and the rewrite directive), the requested URI should be passed to /index.php for processing as a pretty URL. Try:
location / {
try_files $uri /index.php?$query_string;
}
If you need to apply an index to some directories within your hierarchy, you can specify the rule explicitly (rather than using $uri/ and the index directive), by using (for example):
location / {
try_files $uri $uri/index.html /index.php?$query_string;
}
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.
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.