Nginx - Passer toutes les erreurs 404 à PHP-FPM pour une page d'erreur personnalisée de traitement
Je sais que cela a été demandé un millier de fois, mais toutes les réponses je me suis trouvé tout simplement ne fonctionne pas (pour moi, ou le plus souvent à l'origine de l'OP de ces questions)... Donc, je vais essayer d'expliquer le problème du mieux que je peux et j'espère que nous pourrons le faire fonctionner pour moi et pour les autres qui ont demandé avant.
Ma config Nginx (avec beaucoup d'autres chose sans pertinence supprimée) est comme suit:
http {
# Config from here removed
server {
listen 80;
listen 443 ssl;
server_name mydomain.co.uk;
ssl_certificate /xxxxxxx.crt;
ssl_certificate_key /xxxxxxx.key;
# Custom error pages
root /var/www/viovet_frontend;
error_page 404 = /error404.php;
# Any simple .php page
location ~ \.php$ {
root /var/www/xxxxxx;
#index index.php index.html;
include /etc/nginx/fastcgi.conf;
fastcgi_pass phpfastcgiservers;
include fastcgi_params;
fastcgi_intercept_errors on;
}
# Lots more config and re-write rules here removed
}
upstream phpfastcgiservers {
server xxxxx1:9001;
server xxxxx2:9001;
server xxxxx3:9001;
fair;
}
}
Tout ce que je suis en train de faire est d'obtenir Nginx pour attraper tous les 404s et de les envoyer à PHP-FPM via location ~ \.php$
d'avoir une page d'erreur personnalisée indiqués à l'utilisateur, mais je reçois toujours le standard de Nginx page d'erreur.
Les urls suivantes devraient tout de montrer la sortie de mydomain.co.uk/error404.php
:
- mydomain.co.royaume-uni/someNonExistantFile (n'a pas à correspondre à n'importe quel emplacement des blocs)
- mydomain.co.uk/someMissingFile.php (adapté de l' .php emplacement du fichier, mais le fichier n'existe pas)
Mais en fait ils montrent la norme Nginx page 404. Si le location ~ \.php$
renvoie un autre code d'erreur 404 (e.g 5xx), alors nous ne voulons pas participer, il suffit de retourner le contenu et les en-têtes que FastCGI retournée dans la première place.
J'espère qu'un sens et que quelqu'un peut vous aider. Je vous remercie à l'avance.
EDIT: j'ai essayé d'ajouter recursive_error_pages on;
à la ligne après # Custom error pages
mais c'est en fait la cause de toute Nginx 404 Not Found
erreurs pour devenir Nginx 500 Internal Server Error
erreurs.
EDIT: Ajouter d'autres fichiers:
/etc/nginx/fastcgi.conf
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
fastcgi_params
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
Je suppose que je n'ai probablement pas besoin de ces deux de toute façon! 😉
PHP-FPM et Nginx sont sur des machines différentes. Faire ce (seul) l'habitude d'aider Nginx l'envoyer à PHP-FPM.
OriginalL'auteur Luke Cousins | 2014-04-16
Vous devez vous connecter pour publier un commentaire.
J'ai enfin travaillé plus de. Merci à tous pour vos conseils et de mettre le temps à écrire la réponse.
Le problème est que notre
error404.php
était de retourner à notre page d'erreur avec un 404 not Found-tête de trop (à l'aide deheader('HTTP/1.0 404 Not Found');
) et Nginx était alors intercepter cette erreur commerecursive_error_pages
est désactivé (par défaut) et il montrait sa propre page d'erreur 404. La coupure defastcgi_intercept_errors
est la solution. Si on enlève leheader('HTTP/1.0 404 Not Found');
à partir de l'erreur de fichier puis nous aurions l'erreur, mais avec un200
qui n'est évidemment pas ce que nous voulons.Ce n'est pas, cependant, de résoudre le problème de l'accès à une page manquante qui se termine avec
.php
(de sorte qu'il corresponde à l'emplacement du bloc que nous rentrons maintenant le standard de PHP-FPM réponse à ceux d'une 404-tête avec le corpsFile not found.
. Je pourrais utiliser Nate répondre pour contourner ce problème, mais je préfère ne pas besoin de spécifier tous les noms de fichier. Je vais chercher une autre solution pour cela et de le poster ici lorsque je reçois un.EDIT: plus solution complète:
Vous avez besoin pour intercepter les erreurs dans votre php emplacement de bloc (
fastcgi_intercept_errors
eston
) et ensuite avoir un autre bloc pour vos pages d'erreur lorsque vous n'avez pas les intercepter. Voir cette config exemple:Cela signifie que l'un de vos pages PHP qui retourne un code d'état HTTP 404 ont leur propre contenu (le cas échéant) ignoré et le contenu de votre
/http_errors/404.php
fichier sera utilisé à la place.Quel est le but de
/http_errors/
? Ayant un emplacement de bloc qui correspond '404.php' fonctionne aussi bien.C'est incroyablement utile. Merci d'avoir pris le temps de poster ce qui a fonctionné.
OriginalL'auteur Luke Cousins
Je crois que ce que vous demandez n'est pas possible avec nginx seul - sauf si vous configurez chaque connus .php fichier manuellement. Si vous pouvez lister le plus connu .php les fichiers, vous pouvez détecter un attendu 404 basé sur cette information. Au lieu de capturer tous .les fichiers php avec une expression régulière, vous spécifiez connu les fichiers php:
Remplacer
location ~ \.php$ {}
avec quelque chose comme:Ce ne sera cependant pas capturer une 404 généré par votre machine à php-fpm si une demande pour un soi-disant connu fichier php comme index.php retourne 404, même si vous avez dit nginx il devrait exister.
Une solution complète aurait probablement besoin d'un serveur supplémentaire en face de votre serveur nginx qui détecte une réponse 404 à partir de php-fpm/nginx, qui serait ensuite proxy un autre aller-retour demande à votre backend pour la error404.php fichier. Si vous souhaitez toujours exécuter sur le problème de votre error404.php fichier aussi retourner une erreur 404. J'ai regardé dans Vernis pour voir s'il détecte un 404 pourrait générer une deuxième demande au serveur d'origine pour une page d'erreur, mais malheureusement, le vcl_backend_error ne peut que servir la 404 ou réessayer la demande. Vernis - ou quelque chose de semblable, pourrait disposer d'un moyen d'accomplir ce que vous voulez, mais il ne sera pas facile.
Tout ce que je peux dire c'est que c'est une des raisons pour lesquelles la plupart des gens ne pas configurer nginx et php-fpm sur des machines différentes - il provoque des maux de tête comme ça. Si possible, vous devriez vraiment envisager de garder nginx et php-fpm sur la même machine et l'équilibrage de charge des serveurs. Quelle que soit la prestation que vous croyez que vous obtenez à partir de séparation n'est probablement pas la peine de les problèmes supplémentaires.
Merci Nate, j'ai reçu, vous le bounty en tant que bien que votre réponse ne correspond pas du tout à résoudre tous les problèmes, il est le plus proche. J'ai posté une réponse ci-dessous qui, lorsqu'il est combiné avec le vôtre, il permettrait de résoudre tous les problèmes, mais je préfère ne pas besoin de spécifier toutes les les noms de fichiers php si je peux sortir avec elle.
OriginalL'auteur
La
location ~ \.php$
bloc nécessite un try_files à la vérification de l'existence des fichiers. Si n'existe pas, le retour 404, et votre error404.php le prendre.mydomain.co.uk/someNonExistantFile
qui ne correspondent pas n'importe quel emplacement des blocs?OriginalL'auteur Tan Hong Tat
Votre "root /var/www/xxxxxx;" doit être à l'extérieur de l'emplacement"~ .php$" bloquer et avant "error_page 404 = /error404.php;"
Si vous ne parvenez toujours pas à obtenir le désiré à partir de la page d'erreur 404 error404.php, je vous propose de commencer à déboguer à l'aide d'une copie de nginx.conf et puis personnaliser votre error_page à partir de là, parce que ce que nous avons suggéré des œuvres. J'ai utilisé les mêmes configurations pour mon propre serveur.
Si cela ne fonctionne toujours pas, il devrait être un problème en amont.
Vous aussi vous voulez vérifier votre
include /etc/nginx/fastcgi.conf;
inclure fastcgi_params;
pour voir s'il y a des voyous variables. Il peut y avoir des doublons de variables.
Règle générale de pouce sur le débogage. Réduire vos variables. Commencez avec une configuration simple et de travailler votre chemin jusqu'à elle.
error_page 404 = /error404.php;
et ce n'est pas faire une différence. Nous avons aussi d'autres emplacement des blocs qui ne sont pas inclus dans l'extrait ci-dessus qui sont des fichiers statiques, les images, les css, etc qui charge directement à partir de la Nginx machine. Le PHP-FPM instances sont physiquement situés sur d'autres machines. La Nginx machines n'ont pas les fichiers php, ce qui je pense est pourquoi il ne pense pas qu'il peut trouver. Je vais ajouter mes fastcgi_params et fastcgi.conf à la question principale, mais je pense qu'ils sont ok comme tout le reste fonctionneJe suis un peu confus par votre commentaire ci-dessous pour Tan. "Nginx machines n'ont pas les fichiers PHP." Je suis sûr que la proxy_pass à l'amont de servir les fichiers php spécifié dans la racine /var/www/xxxxxx; Avez-vous mis proxy_pass phpfastcgiservers; ?
OriginalL'auteur RyanYJL
La façon correcte
error_page 404 /path/to/404.php;
Je sais que ça fonctionne parce que j'ai construit une application récemment et c'était le programme d'installation pour le traitement des erreurs. veuillez noter que j'utilise la réécriture d'url à supprimer
index.php
de demandes pour chaque répertoire. De cette façon, vous pouvez configurer votre erreur de script pour enregistrer les informations dans votre base de données, ce qui peut être utile pour les difficile à déboguer ajax erreurs, entre autres choses:mon erreur && excuses
OriginalL'auteur r3wt