How can I define a custom 404 error page for a subdirectory?
Any of your requests for the non-existent resources ends up at the location ~ \.php$ { ... }
block where you do not have error_page
directive at all. If you define your custom error page at the server
level, that location inherits that page. You can define two PHP handlers (order of location
blocks matters!):
location ~ ^/es.+\.php$ {
error_page 404 /es/404.php;
... # other content is the same as in the question
}
location ~ \.php$ {
error_page 404 /404.php;
... # other content is the same as in the question
}
or better use a map
block like
map $uri $errpage {
~^/es /es/404.php;
default /404.php;
}
server {
...
error_page 404 $errpage;
}
Nginx - Customizing 404 page
You use the error_page property in the nginx config.
For example, if you intend to set the 404 error page to /404.html
, use
error_page 404 /404.html;
Setting the 500 error page to /500.html
is just as easy as:
error_page 500 /500.html;
Disable direct access to nginx custom error page
Consider storing error pages outside of the main web folder and set a new root
or alias
:
location @errorPage {
root /var/www/error-pages;
...
}
Nginx display custom error page if folder does not exist
This one can't be solved the way you are trying to solve it. The reason is that if
is evil when used in location
context. I have known this for a long time, but I didn't know it can be so evil sometimes.
Generally nginx configuration directives are declarative (for example there is no difference where will you place a directive like proxy_pass
, within the exact location it can be placed anywhere). While in common nginx directives from the rewrite module are the only ones that can be considered as imperative (see the internal implementation chapter from the module documentation), an if
directive is a very special case. After reading the aforementioned implementation description, for a long time I thought that using only directives from the rewrite module inside the if
block will made such a block completely safe one. Unfortunately it isn't true. One of the best descriptions of how this directive actually works was made by Yichun Zhang, an author of famous lua-nginx-module and the OpenResty bundle. If fact every if
directive implicitly creates a nested location which tries to inherit all the declarations from the parent one. However the try_files
directive is not gets inherited (nginx trac ticket), and such a virtual nested location, if being selected to handle the request and having a static content handler, would have a default PRECONTENT
phase handler similar to try_files $uri $uri/ =404
. Error message you received comes from the fact that implicit try_files
directive tries to use the current URI (probably the /
one) and the implicit index
directive can't find an index file inside the webroot /data
directory.
That is, the chosen method won't work. You can try the following instead:
if (!-d /data/$subdomain$domain) {
rewrite ^ /defaults/nothosted.html;
}
location / {
root /data/$subdomain$domain;
try_files $uri $uri/ =404;
index index.html index.htm index.php;
}
location = /defaults/nothosted.html {
internal;
root /data;
}
error_page 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 421 422 423 424 425 426 428 429 431 451 500 501 502 503 504 505 506 507 508 510 511 @error;
location @error {
internal;
ssi on;
auth_basic off;
root /data;
try_files /$subdomain$domain/misc/error.html /$domain/misc/error.html /defaults/error.html =404;
}
This solution has a drawback - the /defaults/nothosted.html
URI won't work for any of the hosted sites. If you find it unacceptable, you can use some kind of unique random string instead of nothosted
one (and rename that nothosted.html
file accordingly).
Related Topics
HTML into PHP Variable (HTML Outside PHP Code)
Tell Selinux to Give Apache Execute Access to PHP Files Outside Document Root
How to Post a Large Amount of Data Within PHP Curl Without Memory Overhead
Parse Timezone Int to String (Timezone Name) (Facebook API)
Check to See If an Email Is Already in the Database Using Prepared Statements
Best Way to Do a Weighted Search Over Multiple Fields in MySQL
PHP How to Go One Level Up on Dirname(_File_)
MySQL Database Won't Start in Xampp Manager-Osx
PHP Call_User_Func VS. Just Calling Function
Sending Messages from PHP to Node.Js
PHP Object of Class Dateinterval Could Not Be Converted to String
Apache Permissions, PHP File Create, Mkdir Fail
Laravel: Auth::User()->Id Trying to Get a Property of a Non-Object
How to Format an Utc Date to Use the Z (Zulu) Zone Designator in PHP
Array Merge on Multidimensional Array
How to Discover Rss Feeds for a Given Url