Redirection PHP - Maîtrisez les codes 301, 302, 307, 308

Xavier Moreau .

1 juin 2026

Illustration expliquant les différences entre les redirections 301, 302 et 307, et comment les utiliser en SEO. Une redirection 301 est permanente, 302 temporaire, et 307 temporaire avec requêtes identiques.

Une redirection côté serveur semble simple, mais en PHP elle touche vite au cache, au comportement du navigateur et à la sécurité. Je la traite toujours comme un contrat HTTP, pas comme un simple changement d’URL. Dans cet article, je détaille la logique de php redirect, le choix du bon code, la mise en place propre en PHP et les erreurs qui cassent le plus souvent les déploiements.

Les points essentiels à garder en tête avant d’écrire une redirection

  • Une redirection PHP envoie une réponse HTTP avec l’en-tête `Location`, puis le client demande la nouvelle URL.
  • Le code de statut compte autant que l’URL : 301 et 308 servent aux migrations permanentes, 302 et 307 aux changements temporaires, 303 après un POST.
  • `header('Location:')` seul vaut 302 dans PHP, donc il faut souvent fixer explicitement le statut.
  • Aucun contenu ne doit sortir avant les en-têtes, sinon la redirection peut échouer ou devenir imprévisible.
  • Ne laisse jamais l’utilisateur fournir une URL brute sans contrôle, sinon tu ouvres la porte aux redirections malveillantes.
  • Dans une API, le choix du code change le contrat : préserver ou non la méthode HTTP n’a pas le même impact selon le cas d’usage.

Ce que fait réellement une redirection PHP

Dans une application backend, une redirection n’est pas un artifice visuel. Le serveur répond avec un statut 3xx et un en-tête Location, puis le client suit automatiquement la nouvelle adresse. C’est ce mécanisme qui permet de migrer une route, de renvoyer un utilisateur après authentification ou de canoniser une URL sans bricolage côté navigateur.

Je distingue toujours trois familles de cas. La redirection HTTP sert à transférer proprement la requête vers une autre ressource. La réécriture interne, elle, garde l’URL visible inchangée dans la barre d’adresse. Enfin, une redirection JavaScript ou via reste un plan B, utile seulement quand on ne contrôle plus le serveur. Pour du backend et des API, le serveur doit rester l’autorité, pas le client.

En pratique, la plupart des besoins se ressemblent : changement de nom de page, migration de domaine, page de maintenance, flux de connexion, ou ancien endpoint qu’on ne veut plus servir directement. L’intérêt d’une vraie redirection HTTP, c’est qu’elle parle à la fois aux navigateurs, aux robots et aux clients techniques. Le point décisif, ensuite, est de choisir le bon code de statut pour que tous interprètent la transition de la même façon.

Illustration expliquant les redirections d'URL (301, 302, 303), un concept clé pour le SEO et le php redirect.

Choisir le bon code HTTP pour ne pas brouiller le signal

Le choix du statut est souvent ce qui différencie une redirection propre d’un raccourci fragile. La documentation PHP rappelle d’ailleurs que header('Location:') renvoie par défaut un 302 si aucun code n’est précisé. C’est pratique pour tester vite, mais insuffisant dès qu’il y a un vrai enjeu de cache, de méthode HTTP ou de référencement.

Code Usage courant Comportement de la méthode Quand je le choisis
301 Redirection permanente La méthode peut être modifiée par certains clients Migration définitive d’une URL, changement de structure, canonicalisation
302 Redirection temporaire La méthode peut être modifiée par certains clients Test, bascule temporaire, page indisponible pour un court moment
303 Voir autre chose après un envoi de formulaire La requête suivante devient un GET Pattern POST-Redirect-GET, page de confirmation après soumission
307 Redirection temporaire stricte La méthode et le corps sont conservés API ou parcours où il faut garder exactement la requête d’origine
308 Redirection permanente stricte La méthode et le corps sont conservés Migration permanente d’un endpoint non-GET sans changer le verbe

Pour résumer simplement : 301 et 308 servent à dire “c’est déplacé pour de bon”, tandis que 302 et 307 disent “c’est temporaire”. La différence entre 301/302 d’un côté et 307/308 de l’autre tient surtout à la conservation de la méthode. MDN souligne précisément que 303 force un retour en GET, ce qui est idéal après un POST quand on veut éviter un renvoi accidentel du formulaire au rafraîchissement.

En migration SEO, j’utilise plutôt 301 quand l’URL cible est stable et durable. En API, je préfère 307 ou 308 si le client doit conserver le verbe et le corps, par exemple sur une opération POST ou PUT. Une fois le code choisi, il reste à l’écrire proprement pour éviter les effets de bord.

Mettre en place la redirection correctement en PHP

La forme la plus simple consiste à envoyer l’en-tête Location puis à arrêter le script. C’est la base, mais il y a une règle que je ne contourne jamais : tu coupes l’exécution juste après. Sinon, le code suivant peut continuer à produire des effets secondaires, écrire du contenu ou déclencher d’autres traitements alors que le client est déjà parti ailleurs.

Pour une migration permanente, je préfère être explicite sur le code :

Et après un POST, le schéma le plus propre reste souvent celui-ci :

Quelques réflexes me paraissent non négociables :

  • placer la redirection avant tout affichage HTML ou espace blanc inutile ;
  • utiliser un chemin relatif si la cible reste dans le même site, par exemple /compte ;
  • employer une URL absolue si la destination change de domaine ;
  • choisir le code de statut au lieu de laisser le 302 implicite ;
  • terminer immédiatement avec exit ou die.

Cette mécanique est simple, mais elle ne pardonne pas les entrées mal contrôlées. C’est précisément là que les problèmes de sécurité et de stabilité commencent.

Éviter les pièges de sécurité et les boucles

Le risque classique, c’est la redirection ouverte. L’utilisateur fournit une URL de destination, le serveur la recopie, et un attaquant s’en sert pour envoyer quelqu’un vers un site de phishing. OWASP recommande de ne pas accepter une URL brute comme cible et de préférer un identifiant court, mappé côté serveur vers une destination autorisée.

Je conseille donc un modèle simple : le client envoie une clé, pas une URL complète. Le backend fait la correspondance dans une liste blanche locale. Exemple :

 '/tableau-de-bord',
    'profil' => '/compte/profil',
    'facturation' => '/compte/facturation',
];

$key = $_GET['next'] ?? 'dashboard';
$target = $targets[$key] ?? '/tableau-de-bord';

header('Location: ' . $target, true, 302);
exit;

Si une destination externe est vraiment nécessaire, je préfère parser l’URL et comparer strictement le domaine attendu. Pas d’expression régulière approximative, pas de tolérance sur le schéma, pas de raccourci “on verra en production”. En matière de redirection, les petites libertés deviennent vite des failles.

L’autre piège fréquent est la boucle infinie. Elle apparaît quand une règle renvoie vers une URL qui repasse immédiatement dans la même règle, souvent après une migration partielle ou un mauvais test de session. Pour la casser, je vérifie toujours la cible effective avant d’émettre l’en-tête, et je surveille les fichiers inclus qui pourraient envoyer du contenu invisible avant la redirection.

Enfin, n’ignore pas les symptômes classiques de headers already sent. Un espace avant , un echo oublié, ou un fichier inclus qui affiche quelque chose suffit à bloquer la réponse. Dans ce cas, je traite le problème à la source plutôt que de masquer la panne avec du buffering. La technique est utile, mais elle ne remplace pas une réponse propre.

Une fois ces bases sécurisées, la vraie question devient : faut-il vraiment rediriger dans un backend ou une API, et si oui, à quel moment exactement ?

Redirections utiles dans une API ou un backend moderne

Dans une interface web classique, la redirection est naturelle. Dans une API, elle doit être plus réfléchie. Un client machine ne “clique” pas, il enchaîne des requêtes selon un contrat. Si je redirige trop souvent ou au mauvais code, je risque de casser ce contrat, surtout sur des clients HTTP stricts ou sur des intégrations tierces.

Je réserve les redirections API à quelques scénarios précis :

  • migration d’un endpoint vers une nouvelle version stable ;
  • bascule temporaire pendant une maintenance ou un incident ;
  • flux POST-Redirect-GET sur une partie web du backend ;
  • retour après authentification vers une page de reprise ;
  • déplacement définitif d’une ressource avec conservation du verbe quand c’est nécessaire.

Pour une soumission de formulaire ou un parcours utilisateur, le trio le plus robuste reste souvent POST puis 303 puis page de confirmation. Cela évite les doublons lors du rafraîchissement. Pour une API qui doit conserver la méthode, je privilégie 307 ou 308, car ils gardent le corps de la requête intact. C’est important dès qu’un client envoie des données sensibles ou structurées qu’il ne faut pas transformer en GET par accident.

Dans les architectures plus sérieuses, je me méfie aussi des redirections “pour masquer” un problème de conception. Si un service change trop souvent d’URL, si une API passe son temps à rediriger vers une autre, il est souvent plus propre de corriger le routage au niveau du proxy, du gateway ou de la configuration applicative plutôt que d’imposer un détour au client. La redirection est un outil de transition, pas un substitut permanent à une architecture claire.

Une fois ce cadre posé, il ne reste plus qu’à vérifier les derniers détails avant mise en production.

Les derniers contrôles que je fais avant de déployer

Avant d’envoyer une redirection en production, je passe toujours par une vérification courte mais stricte. Elle me prend peu de temps et m’évite les problèmes les plus coûteux à diagnostiquer après coup :

  • la cible est-elle bien celle voulue, et pas une URL saisie par l’utilisateur ?
  • le bon code HTTP est-il envoyé explicitement ?
  • aucun contenu n’est-il sorti avant les en-têtes ?
  • le script se termine-t-il immédiatement après la redirection ?
  • la règle ne peut-elle pas créer une boucle sur une route déjà migrée ?
  • le comportement est-il correct avec curl, un navigateur et un client API ?
  • la migration doit-elle être mise en cache ou rester temporaire ?

Je vérifie aussi le contexte de déploiement : proxy, CDN, cache applicatif, HSTS, pages de maintenance et éventuelles règles du serveur web peuvent modifier le résultat perçu par le client. Sur un site à fort trafic, la différence entre un 302 laissé par défaut et un 301 ou 308 assumé peut changer la façon dont le trafic, les robots et les intégrations réagissent pendant des semaines. Si je dois retenir une seule règle, c’est celle-ci : une redirection n’est pas juste une URL de remplacement, c’est une décision de protocole.

Quand la logique est claire, la mise en œuvre en PHP reste très légère. Ce qui fait la différence, ce ne sont pas des lignes de code supplémentaires, mais le choix du bon statut, la maîtrise des entrées et le respect du contrat HTTP jusqu’au bout.

Questions fréquentes

Utiliser `header('Location:')` seul en PHP génère par défaut un code 302 (temporaire). Pour une redirection permanente ou pour conserver la méthode HTTP, il est crucial de spécifier explicitement le code de statut (ex: 301, 308) via `http_response_code()`.
Les deux sont des redirections permanentes. La 301 peut modifier la méthode de la requête (ex: POST devient GET), tandis que la 308 conserve la méthode et le corps de la requête d'origine. La 308 est préférable pour les API.
La 303 est idéale après un formulaire POST. Elle indique au client de récupérer la ressource cible avec une requête GET, évitant ainsi la soumission accidentelle du formulaire si l'utilisateur rafraîchit la page de confirmation.
N'acceptez jamais une URL brute fournie par l'utilisateur. Utilisez une liste blanche de destinations autorisées côté serveur ou validez strictement l'URL si une cible externe est indispensable, pour prévenir les redirections ouvertes malveillantes.
Oui, il est impératif d'appeler `exit;` ou `die;` immédiatement après `header('Location:')`. Cela empêche le script de continuer son exécution et d'envoyer du contenu inattendu qui pourrait corrompre la redirection ou causer des effets secondaires.

Évaluer l'article

Moyenne: 0.0 / 5 · 0 évaluations

Tags

php redirect redirection php 301 redirection php 302 redirection php 307 redirection php 308 redirection php header location
Autor Xavier Moreau
Xavier Moreau
Je m'appelle Xavier Moreau et je cumule 14 ans d'expérience dans le développement web, avec un accent particulier sur JavaScript, le backend, le NoSQL et la sécurité. Mon intérêt pour ces domaines a émergé dès mes débuts dans la programmation, où j'ai découvert la puissance des technologies web et leur capacité à transformer des idées en réalité. J'aime expliquer des concepts complexes de manière accessible, en aidant les lecteurs à naviguer dans les défis techniques qu'ils rencontrent. Au fil des ans, j'ai développé une expertise solide en vérifiant mes sources, en comparant les informations et en simplifiant des sujets parfois ardus. Je m'efforce toujours de fournir des contenus utiles, précis et à jour, en suivant les tendances du secteur et en organisant mes connaissances de manière claire. Mon objectif est d'accompagner les passionnés et les professionnels du développement web dans leur quête de compréhension et d'innovation.

Commentaires (0)

Ajouter un commentaire