Gestion « propre » des erreurs 404 dans un site SPIP

Comment renvoyer, vers la même page d’erreur (type « 404 Not found »), toutes les requêtes liées à du contenu non trouvé dans SPIP (« vraies » erreurs 404, mais aussi articles, rubriques, etc., avec identifiant inexistant).

1. Présentation du problème

Plusieurs raisons peuvent conduire un internaute (d’un site sous SPIP) à naviguer vers du contenu inexistant :

-  L’URL demandée ne correspond à aucun fichier du serveur (même après réécriture de l’URL) : il s’agit d’une erreur 404 « authentique », donc gérée par le serveur web (Apache, etc.).

-  L’URL demandée correspond bien à un squelette existant de SPIP (article, rubrique, brève, auteur, etc.), mais l’identifiant de l’objet demandé n’est pas trouvé dans la base SPIP : il s’agit d’une simple erreur d’accès aux données de la base SPIP, donc gérée par le moteur SPIP.

Du point de vue de l’utilisateur/internaute (qui se moque finalement de savoir si le site est construit sous SPIP ou autre), il n’est pas forcément intéressant de dissocier ces deux types d’erreurs.

L’objectif de cette contribution est de vous permettre de rediriger toutes ces réponses en erreur vers la même page de type « 404 Not found » [1].

2. Résumé de la solution proposée

-  Les « vraies » erreurs 404 seront traitées à l’aide des paramètres de configuration du serveur web (par exemple un fichier .htaccess dans le cas d’Apache).

-  Les erreurs d’identifiants d’objets SPIP seront gérées dans les squelettes concernés, à l’aide de quelques lignes de PHP.

-  Ces deux types d’erreur renverront vers le même contenu informatif, à savoir (dans mon exemple) le plan du site, agrémenté d’un petit message expliquant l’erreur survenue.

3. Conception de la page d’erreur 404

L’idée pour cette page est de réemployer la page de plan du site prévue dans SPIP : en cas d’erreur 404, l’internaute aura ainsi la possibilité de se rediriger vers le contenu qui l’intéresse, ou vers la page de recherche, etc.


3.1. Une nouvelle page d’erreur, basée sur le plan du site

Une fois élaboré un squelette de plan bien constitué (arborescence des rubriques et/ou des articles), vous vous retrouvez avec les deux fichiers :

-  « plan.html » (squelette)

-  « plan.php3 » (fichier PHP d’appel du squelette)

Pour personnaliser ce plan afin de mentionner une éventuelle erreur 404, créez un nouveau fichier « 404.php3 », contenant juste une ligne de plus que le fichier « plan.php3 » :

<?php

$error404 = true;   //ligne ajoutée
$fond = "plan";
$delais = 2 * 3600;

include ("inc-public.php3");

?>

Seule la ligne « $error404 = true; » a été ajoutée ; mais ce fichier PHP fait appel au même squelette « plan ».


3.2. Gestion des erreurs 404 dans le squelette du plan

Le squelette du plan du site (plan.html) est alors modifié pour prendre en compte cette variable PHP « $error404 », afin de modifier légèrement certains affichages (titre de la page, message indiquant qu’une erreur 404 s’est produite, etc.).

Voici le genre de modifications qui peuvent être apportées :

[Début du squelette]

<?php
	/*
		Gestion de la variable $error404,
		afin qu'un appel SANS la variable
		(par le fichier plan.php3) affiche
		simplement le plan du site sans
		messages d'erreur.
	*/
	if(!isset($error404)) { $error404 = false; }
?>

<html>
<head>
	<title><?php
		print($error404 ? "Erreur 404" : "Plan du site");
	?></title>
<?php if($error404) { ?>
	<meta name="robots" content="noindex, follow">
<?php } ?>
	<base href="[(#URL_SITE_SPIP)]/" />

[...Suite du squelette...]

</head>

<body>

[...Suite du squelette...]

	<h1><?php
		print($error404 ? "Erreur 404" : "Plan du site");
	?></h1>

<?php if($error404) { ?>
	<p style="color: red;"><b>La page demandée
	est introuvable.</b></p>
	<p>Veuillez utiliser le plan ci-dessous
	pour naviguer dans le site.</p>
	<p>Si ce problème est récurrent, merci de
	<a href="mailto:webmaster@mon_site_spip.test">contacter
	le webmaster</a>.</p>
<?php } ?>

[...Suite et fin du squelette...]

Bien sûr, vous pouvez agencer ces petites modifications comme bon vous semble dans votre squelette.

L’idée est simplement d’exploiter à loisir la variable « $error404 » afin de personnaliser l’affichage :

-  Si la page « plan.php3 » est appelée, le plan s’affiche simplement.

-  Si une erreur 404 est déclenchée (et traitée par le script « 404.php3 » au moyen des mécanismes décrits plus loin), le plan s’affiche avec un titre adéquat et quelques messages d’explication, et la balise META appropriée garantit que cette version du plan ne sera pas conservée par les moteurs de recherche [2].

4. Gestion des « vraies » erreur 404

La configuration du serveur web pour traiter les erreurs 404 sort du cadre de cet article :

-  Pour personnaliser le fichier .htaccess sur un serveur Apache, consultez la contribution Le fichier .htaccess.

-  Pour les autres serveurs web, consultez la documentation appropriée.

Dans tous les cas, faites en sorte que les erreurs 404 appellent le fichier /404.php3
Par exemple, sur un serveur Apache, ajoutez la ligne suivante dans le fichier .htaccess situé à la racine de votre site SPIP :

ErrorDocument 404 /404.php3

5. Gestion des articles, rubriques, et autres objets SPIP appelés avec un identifiant inexistant

Les boucles SPIP permettent d’afficher du code « alternatif », dans le cas où la boucle ne trouve aucune réponse [3].

Ce mécanisme, utilisant la balise (optionnelle) finale <//Bn> de la boucle, est décrit dans la documentation SPIP.

L’idée ici est d’utiliser ce mécanisme « natif » SPIP non pas pour afficher un message particulier (tel que « L’article demandé n’existe pas. ») mais pour provoquer l’affichage de la page d’erreur créée plus tôt.

Il suffit pour cela d’insérer au tout début des squelettes concernés un code PHP tel que :

<?php
	<BOUCLE_test404(ARTICLES){id_article}>
		/*
			Ne rien faire si l'article existe,
			mais laisser un court commentaire
			tel que celui-ci pour que la
			boucle fonctionne.
		*/
	</BOUCLE_test404>
		header("HTTP/1.1 404 Not found");
		header("Status: 404 Not found");
		include("404.php3");
		exit();
	<//B_test404>
?>

Le code ci-dessus doit être ajouté au début squelette « article.html ».

Les en-têtes HTTP précisent au navigateur (ou au robot / moteur de recherche qui a demandé l’URL fautive) qu’il s’agit d’une erreur 404 : ainsi, les moteurs de recherche n’indexeront pas (ou désindexeront correctement) l’URL qui a provoqué l’erreur.

Des adaptations mineures de la boucle doivent bien sûr être faites pour tous les squelettes correspondant aux pages du site susceptibles d’être appelées avec un identifiant (selon votre exploitation de SPIP dans votre site : articles, rubriques, brèves, auteurs, forums, mots, documents, sites/syndication, ...).

Important :
Les squelettes propres à une rubrique doivent également être ainsi adaptés, afin de gérer par exemple le cas d’un article existant mais non publié : le squelette appelé par SPIP est bel et bien celui de la rubrique X (s’il existe) « article-X.html » ou « article=X.html », même si la boucle considère ensuite que l’article est inexistant.
Ce code est donc à adapter et placer au tout début de TOUS les squelettes qui correspondent à un type de page dans laquelle une boucle majeure se base sur un identifiant (id_article, id_rubrique, etc.).

Par exemple au début du (ou des) squelettes de rubriques :

<?php
	<BOUCLE_test404(RUBRIQUES){id_rubrique}>
		/*
			Ne rien faire si la rubrique existe,
			mais laisser un court commentaire
			tel que celui-ci pour que la
			boucle fonctionne.
		*/
	</BOUCLE_test404>
		header("HTTP/1.1 404 Not found");
		header("Status: 404 Not found");
		include("404.php3");
		exit();
	<//B_test404>
?>

Au final, dans tous les cas, si l’objet SPIP indispensable à la page n’est pas trouvé, seul le contenu de la page 404.php3 s’affiche.

6. Conclusion

Cette solution, relativement simple, permet à toutes les erreurs de type « contenu non trouvé » de rediriger « proprement » (et avec les en-tête HTTP adéquats) l’internaute vers la même page d’erreur, qu’il s’agisse réellement d’une URL introuvable ou d’un objet SPIP introuvable (ou non-publié).

Vos commentaires sont les bienvenus !

Notes

[1Cette solution peut tout à fait être adaptée pour traiter d’autres types d’erreurs (403, etc.).

[2La balise <base>, quant à elle, permet l’affichage correct des images, styles, etc., dans le cas où le squelette d’erreur est affiché à partir d’une « vraie » erreur 404 déclenchée par une URL correspondant à un sous-répertoire de la racine SPIP.
Par exemple la requête http://www.mon_site_spip.test/un_sous_repertoire/fichier_inexistant.html affichera quand même correctement le contenu de la page http://www.mon_site_spip.test/404.php3

[3C’est-à-dire :
• soit les critères de sélection (identifiant, etc.) ne correspondent à aucun objet dans la base SPIP ;
• soit l’objet existe mais n’est pas à l’état « publié » (articles, brèves...).

La version de développement de SPIP intègre une gestion similaire et sera disponible dans la version 1.8 qui sortira.... quand les développements seront stabilisés ;-)

Discussion

6 discussions

  • galart

    Bonjour,

    Merci pour la contrib.
    J’ai essayé de l’installer sur un site en spip 2.1, mais, si l’envoi des entêtes http se fait correctement, je n’arrive pas à faire fonctionner l’include. J’ai tenté plusieurs écritures, dont celle préconisée par Bourbaki (include("http://www.mondomaine.tlm/spip.php?page=404") ;), mais sans succès.
    En tapant l’adresse d’un article dépublié, je tombe sur : Oups ! Petit problème... Ce lien semble brisé. Ce qui n’est pas le message idéal à faire passer aux visiteurs...

    Toute aide sera la bienvenue

    Répondre à ce message

  • Bonjour,

    Merci pour cette contribution.

    Je signale au passage qu’elle est compatible avec la version spip 1.9.1 j’ai réussi à l’installer en modifiant l’adresse d’inclusion de la page 404 qui n’est plus compatible avec les versions > 1.9 :

    </BOUCLE_test404>
    		header("HTTP/1.1 404 Not found");
    		header("Status: 404 Not found");
    		{{include("404.php3");}}
    		exit();
    	<//B_test404>

    remplacé par :

    </BOUCLE_test404>
    		header("HTTP/1.1 404 Not found");
    		header("Status: 404 Not found");
    		{{include("http://www.mondomaine.tlm/spip.php?page=404");}}
    		exit();
    	<//B_test404>

    Répondre à ce message

  • 2

    En appelant une URL de type article.php ?rien=1&id_article=88, cela plante le site :

    « Site en travaux
    Attention : un problème technique (serveur MySQL) empêche l’accès à cette partie du site. Merci de votre compréhension. »

    Ce n’est pas le cas des rubriques.

    Pouvez-vous vérifier ?

    • A priori ce problème ne doit pas être lié à la gestion des erreurs 404...

      Vérifiez votre installation SPIP et tentez éventuellement une réparation de la base dans l’interface d’admin (ce message est généralement affiché lorsque la base de données est corrompue, il me semble)

      Je ne pense pas que les quelques lignes de code proposées dans cette contrib puissent provoquer une telle erreur - mais le meilleur moyen de le savoir est de les retirer (ou de les commenter /* ... */) et de voir ce qui se passe lorsqu’elle ne sont pas exécutées...

      Si vous souhaitez plus d’aide, envoyez-nous un lien vers votre squelette article...

      Bonne chasse au bug !

    • Bonjour,

      Je ne sais pas si ce post est bien placé . Je n’ai pas de réponse dans le forum.
      J’aurai vraiment besoin d’aide svp (d’autant plus qu’avec la rentrée, il devrait être présenté prochainement )...

      Comme beaucoup d’entre vous , j’ai le message «  erreur dans la requête : Aucun résultat.Le chemin que vous avez choisi ne semble pas valide. Veuillez retourner à la page précédente et vérifier les informations fournies.  » ...
      ... quand je clique sur des liens d’une rubrique
      (ex http://arrassoc.free.fr/rubrique.php3 ?id_rubrique=118).

      Les liens s’affichent bien en prévisualisation dans l’espace privé ou public mais pas quand nous ne sommes pas identifiés. J’ai pourtant vérifié. Les articles en question sont bien publiés.
      J’ai lu sur le forum le message d’Alainf à ce sujet mais je n’ai trouvé aucune page vide qui pourrait expliquer ce bug ? Où faut il que je cherche Dans /écrire ou dans /squelette ?

      Je précise que mon site est hébergé chez free. J’ai lu les remarques à ce sujet mais j’utilise un squelette personnalisé et je souhaite également utiliser la contribution pour limiter l’accès à certaines rubriques. Je ne peux donc pas facilement passer sous spip 1.9

      Pouvez vous m’aider ? Tout du moins m’aiguiller ?
      Merci par avance

    Répondre à ce message

  • 3

    Mmmmmh... Pourquoi ne pas se contenter de substituer bêtement au natif : « L’article (ou la rubrique...) demandé(e) n’existe pas » le message d’erreur 404 du site dans les squelettes, sans <include> et sans rajouter de php ? Si l’identifiant appelé est dans la base et publié, son contenu s’affiche, sinon c’est le message d’erreur qui s’affiche - il n’y a pas redirection, mais l’internaute reçoit quand même un message explicite. Les « vraies » erreurs 404 restant gérées via htaccess. Bon, c’est un traitement minimaliste... mais encore plus simple.

    • deux messages de forums plus bas, tu as un lien vers une contrib qui fait ce que tu proposes

    • La principale motivation de ma contrib et d’envoyer des en-têtes HTTP correspondant à une erreur (404 en l’occurrence), quelle que soit la raison du contenu manquant - et ce, principalement, à destination des moteurs de recherche et autres crowlers automatiques.

      En effet, sans en-têtes adéquats, il est toujours possible à un moteur de recherche (Google, etc.) d’indexer une URL correcte mais correspondant à un article (ou une rubrique, un auteur, etc.) inexistant.

      A fortiori, avec la réécriture des URL SPIP sous une forme sans query-string (par exemple http://www.monsitespip.com/article1.html), un moteur de recherche peut conserver indéfiniment l’URL d’un article supprimé de votre site SPIP si l’URL en question ne renvoie qu’à un message d’erreur visible dans la page mais sans les en-têtes HTTP d’erreur appropriés...

      Si vous supprimez de temps en temps des articles, rubriques, etc. de votre site SPIP, mais que les pages correspondantes ont déjà été indexées par des moteurs de recherche, seuls des en-têtes HTTP 404 peuvent commander à ces derniers de dé-référencer les pages en question lors du prochain passage de leur robot...

      Sans cela, le risque serait, à terme, d’être référencé dans des moteurs de recherche avec quantités d’URLs pointant vers du contenu SPIP inexistant - ce qui ne fait pas très sérieux...

    • Oui. En l’occurence il s’agissait d’une solution basique pour un petit site peu dynamique (et sans rewriting)... la multiplication de mauvaises indexations sera dans ce cas assez limitée. C’était une suggestion minimaliste, cette contrib est plus exhaustive...

    Répondre à ce message

  • Je n’ai pas tout utilisé mais les modifs offertes à article.html et rubrique.html fonctionnent impec. C’est tout simple comme truc, mais il fallait encore y penser !

    Répondre à ce message

  • à noter : une autre contribution sur le même sujet

    Répondre à ce message

Ajouter un commentaire

Avant de faire part d’un problème sur un plugin X, merci de lire ce qui suit :

  • Désactiver tous les plugins que vous ne voulez pas tester afin de vous assurer que le bug vient bien du plugin X. Cela vous évitera d’écrire sur le forum d’une contribution qui n’est finalement pas en cause.
  • Cherchez et notez les numéros de version de tout ce qui est en place au moment du test :
    • version de SPIP, en bas de la partie privée
    • version du plugin testé et des éventuels plugins nécessités
    • version de PHP (exec=info en partie privée)
    • version de MySQL / SQLite
  • Si votre problème concerne la partie publique de votre site, donnez une URL où le bug est visible, pour que les gens puissent voir par eux-mêmes.
  • En cas de page blanche, merci d’activer l’affichage des erreurs, et d’indiquer ensuite l’erreur qui apparaît.

Merci d’avance pour les personnes qui vous aideront !

Par ailleurs, n’oubliez pas que les contributeurs et contributrices ont une vie en dehors de SPIP.

Qui êtes-vous ?
[Se connecter]

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Ajouter un document

Suivre les commentaires : RSS 2.0 | Atom