«Jolis liens» est un sujet souvent demandé, mais rarement expliqué en détail. mod_rewrite est une façon de créer de "jolis liens", mais c'est complexe et sa syntaxe est très laconique, difficile à comprendre, et la documentation suppose un certain niveau de maîtrise de HTTP. Quelqu'un peut-il expliquer en termes simples comment fonctionnent les "jolis liens" et comment mod_rewrite peut être utilisé pour les créer?
Autres noms communs, alias, termes pour les URL propres: URL RESTful, URL conviviales, URL optimisées pour le référencement , slugging et URL MVC (probablement un abus de langage)
apache
.htaccess
mod-rewrite
friendly-url
déceler
la source
la source
reference-mod-rewrite-url-rewriting-explained
est le slug,/questions/20563772/reference-mod-rewrite-url-rewriting-explained
est la jolie URL..htaccess
etmod-rewrite
devraient être mises à jour pour inclure un lien vers cette question, car elles couvrent une grande partie de ce qui est demandé régulièrement. Pensées?Réponses:
Pour comprendre ce qu'est mod_rewrite, vous devez d'abord comprendre le fonctionnement d'un serveur Web. Un serveur Web répond aux requêtes HTTP . Une requête HTTP à son niveau le plus basique ressemble à ceci:
Il s'agit de la simple demande d'un navigateur à un serveur Web qui lui demande l' URL
/foo/bar.html
. Il est important de souligner qu'il ne demande pas de fichier , il ne demande qu'une URL arbitraire. La demande peut également ressembler à ceci:C'est tout aussi valide une demande d'URL, et cela n'a plus évidemment rien à voir avec les fichiers.
Le serveur Web est une application écoutant sur un port, acceptant les requêtes HTTP arrivant sur ce port et renvoyant une réponse. Un serveur Web est entièrement libre de répondre à toute demande de la manière qu'il juge appropriée / de la manière dont vous l'avez configuré pour répondre. Cette réponse n'est pas un fichier, c'est une réponse HTTP qui peut ou non avoir quelque chose à voir avec des fichiers physiques sur n'importe quel disque. Un serveur Web n'a pas besoin d'être Apache, il existe de nombreux autres serveurs Web qui ne sont que des programmes qui s'exécutent de manière persistante et sont attachés à un port qui répondent aux requêtes HTTP. Vous pouvez en écrire un vous-même. Ce paragraphe visait à vous dissocier de toute notion selon laquelle les URL sont directement égales à des fichiers, ce qui est vraiment important à comprendre. :)
La configuration par défaut de la plupart des serveurs Web consiste à rechercher un fichier qui correspond à l'URL sur le disque dur. Si la racine du document du serveur est définie sur, par exemple
/var/www
, il peut rechercher si le fichier/var/www/foo/bar.html
existe et le servir si tel est le cas. Si les extrémités de fichier dans « .php » il appellera l'interpréteur PHP et puis retourner le résultat. Toute cette association est entièrement configurable; un fichier n'a pas besoin de se terminer par ".php" pour que le serveur Web l'exécute via l'interpréteur PHP, et l'URL n'a pas besoin de correspondre à un fichier particulier sur le disque pour que quelque chose se produise.mod_rewrite est un moyen de réécrire la gestion des requêtes internes. Lorsque le serveur Web reçoit une demande pour l'URL
/foo/bar
, vous pouvez réécrire cette URL dans quelque chose d'autre avant que le serveur Web ne recherche un fichier sur le disque correspondant. Exemple simple:Cette règle dit chaque fois qu'une requête correspond à "/ foo / bar", réécrivez-la dans "/ foo / baz". La demande sera alors traitée comme si elle
/foo/baz
avait été demandée à la place. Cela peut être utilisé pour différents effets, par exemple:Cette règle correspond à tout (
.*
) et le capture ((..)
), puis la réécrit pour ajouter ".html". En d'autres termes, s'il/foo/bar
s'agissait de l'URL demandée, elle sera traitée comme si elle/foo/bar.html
avait été demandée. Voir http://regular-expressions.info pour plus d'informations sur la correspondance, la capture et les remplacements d'expressions régulières.Une autre règle souvent rencontrée est la suivante:
Ceci, encore une fois, correspond à tout et le réécrit dans le fichier index.php avec l'URL demandée à l'origine ajoutée dans le
url
paramètre de requête. C'est-à-dire que pour toutes les demandes entrantes, le fichier index.php est exécuté et ce fichier aura accès à la demande d'origine dans$_GET['url']
, afin qu'il puisse faire tout ce qu'il veut avec.Vous mettez principalement ces règles de réécriture dans le fichier de configuration de votre serveur Web . Apache vous permet également * de les mettre dans un fichier appelé
.htaccess
dans la racine de votre document (c'est-à-dire à côté de vos fichiers .php).* Si autorisé par le fichier de configuration Apache principal; c'est facultatif, mais souvent activé.
Qu'est - ce que mod_rewrite ne pas faire
mod_rewrite ne rend pas par magie toutes vos URL "jolies". C'est un malentendu courant. Si vous avez ce lien dans votre site Web:
il n'y a rien que mod_rewrite puisse faire pour rendre ça joli. Pour en faire un joli lien, vous devez:
Changez le lien en un joli lien:
Utilisez mod_rewrite sur le serveur pour gérer la requête à l'URL en
/my/pretty/link
utilisant l'une des méthodes décrites ci-dessus.(On pourrait l'utiliser
mod_substitute
conjointement pour transformer les pages HTML sortantes et leurs liens contenus. Bien que cela représente généralement plus d'efforts que la simple mise à jour de vos ressources HTML.)Il y a beaucoup de choses que mod_rewrite peut faire et des règles de correspondance très complexes que vous pouvez créer, y compris le chaînage de plusieurs réécritures, le proxy de requêtes vers un service ou une machine complètement différent, le retour de codes d'état HTTP spécifiques en tant que réponses, la redirection de requêtes, etc. C'est très puissant et peut être utilisé pour très bien si vous comprenez le mécanisme de requête-réponse HTTP fondamental. Cela ne rend pas automatiquement vos liens jolis.
Voir la documentation officielle pour tous les drapeaux et options possibles.
la source
Pour développer la réponse de deceze , je voulais fournir quelques exemples et explications de certaines autres fonctionnalités de mod_rewrite.
Tous les exemples ci-dessous supposent que vous avez déjà inclus
RewriteEngine On
dans votre.htaccess
fichier.Exemple de réécriture
Prenons cet exemple:
La règle est divisée en 4 sections:
RewriteRule
- lance la règle de réécriture^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$
- C'est ce qu'on appelle le modèle, mais je vais simplement le désigner comme le côté gauche de la règle - ce que vous voulez réécrireblog/index.php?id=$1&title=$2
- appelé la substitution, ou côté droit d'une règle de réécriture - ce que vous voulez réécrire[NC,L,QSA]
sont des indicateurs pour la règle de réécriture, séparés par une virgule, que j'expliquerai plus tardLa réécriture ci-dessus vous permettrait de créer un lien vers quelque chose comme
/blog/1/foo/
et il se chargerait réellement/blog/index.php?id=1&title=foo
.Côté gauche de la règle
^
indique le début du nom de la page - il sera donc réécritexample.com/blog/...
mais pasexample.com/foo/blog/...
(…)
parenthèses représente une expression régulière que nous pouvons capturer en tant que variable dans la partie droite de la règle. Dans cet exemple:([0-9]+)
- correspond à une chaîne avec au moins 1 caractère de longueur et avec uniquement des valeurs numériques (c'est-à-dire 0-9). Cela peut être référencé avec$1
dans le côté droit de la règle-
ou+
(la note+
est échappée avec une barre oblique inverse car sans l'échapper, cela s'exécutera comme une expression régulière caractère de répétition ). Cela peut être référencé avec$2
dans le côté droit de la règle?
signifie que le caractère précédent est facultatif, donc dans ce cas les deux/blog/1/foo/
et/blog/1/foo
réécriraient au même endroit$
indique que c'est la fin de la chaîne que nous voulons faire correspondreDrapeaux
Ces options sont ajoutées entre crochets à la fin de votre règle de réécriture pour spécifier certaines conditions. Encore une fois, il existe de nombreux indicateurs différents que vous pouvez lire dans la documentation , mais je vais passer en revue certains des indicateurs les plus courants:
L'indicateur aucune casse signifie que la règle de réécriture est insensible à la casse, donc pour l'exemple de règle ci-dessus, cela signifierait que les deux
/blog/1/foo/
et/BLOG/1/foo/
(ou toute variation de ceci) seraient mis en correspondance.Le dernier indicateur indique qu'il s'agit de la dernière règle à traiter. Cela signifie que si et seulement si cette règle correspond, aucune autre règle ne sera évaluée dans le traitement de réécriture en cours. Si la règle ne correspond pas, toutes les autres règles seront essayées dans l'ordre habituel. Si vous ne définissez pas l'
L
indicateur, toutes les règles suivantes seront ensuite appliquées à l' URL réécrite .Depuis Apache 2.4, vous pouvez également utiliser l'
[END]
indicateur. Une règle correspondante avec elle mettra fin complètement au traitement des alias / réécriture. (Alors que le[L]
drapeau peut souvent déclencher un deuxième tour, par exemple lors de la réécriture dans ou hors de sous-répertoires.)L'indicateur d'ajout de chaîne de requête nous permet de transmettre des variables supplémentaires à l'URL spécifiée qui seront ajoutées aux paramètres get d'origine. Pour notre exemple, cela signifie que quelque chose comme
/blog/1/foo/?comments=15
chargerait/blog/index.php?id=1&title=foo&comments=15
Ce drapeau n'est pas celui que j'ai utilisé dans l'exemple ci-dessus, mais je pense qu'il vaut la peine d'être mentionné. Cela vous permet de spécifier une redirection http, avec la possibilité d'inclure un code d'état (par exemple
R=301
). Par exemple, si vous vouliez faire une redirection 301 sur / myblog / vers / blog / vous écririez simplement une règle quelque chose comme ceci:Réécrire les conditions
Les conditions de réécriture rendent les réécritures encore plus puissantes, vous permettant de spécifier des réécritures pour des situations plus spécifiques. Il y a beaucoup de conditions que vous pouvez lire dans la documentation , mais je vais aborder quelques exemples courants et les expliquer:
Il s'agit d'une pratique très courante, qui ajoutera au début de votre domaine
www.
(s'il n'y est pas déjà) et exécutera une redirection 301. Par exemple, le charger voushttp://example.com/blog/
redirigerait vershttp://www.example.com/blog/
C'est un peu moins courant, mais c'est un bon exemple de règle qui ne s'exécute pas si le nom de fichier est un répertoire ou un fichier qui existe sur le serveur.
%{REQUEST_URI} \.(jpg|jpeg|gif|png)$ [NC]
n'exécutera la réécriture que pour les fichiers avec une extension de fichier jpg, jpeg, gif ou png (insensible à la casse).%{REQUEST_FILENAME} !-f
vérifiera si le fichier existe sur le serveur actuel et n'exécutera la réécriture que si ce n'est pas le cas%{REQUEST_FILENAME} !-d
vérifiera si le fichier existe sur le serveur actuel et n'exécutera la réécriture que si ce n'est pas le casla source
Références
Stack Overflow dispose de nombreuses autres ressources intéressantes pour commencer:
(N'oubliez pas de supprimer la barre oblique dans les
^/
préfixes de modèle pour l'.htaccess
utilisation.)Et des aperçus des expressions régulières adaptées aux nouveaux arrivants, même:
Espaces réservés souvent utilisés
.*
correspond à tout, même une chaîne vide. Vous ne voulez pas utiliser ce modèle partout, mais souvent dans la dernière règle de secours.[^/]+
est plus souvent utilisé pour les segments de chemin. Cela correspond à tout sauf à la barre oblique.\d+
ne correspond qu'aux chaînes numériques.\w+
correspond aux caractères alphanumériques. C'est essentiellement un raccourci pour[A-Za-z0-9_]
.[\w\-]+
pour les segments de chemin de type "slug", en utilisant des lettres, des chiffres, des tirets-
et_
[\w\-.,]+
ajoute des points et des virgules. Préférez un\-
tiret échappé dans les[…]
classes de caractères.\.
désigne une période littérale. Sinon, en.
dehors de[…]
est un espace réservé pour tout symbole.Chacun de ces espaces réservés est généralement placé
(…)
entre parenthèses en tant que groupe de capture. Et le motif entier souvent dans les^………$
marqueurs de début + fin. La citation de "modèles" est facultative.Réécrire les règles
Les exemples suivants sont centrés sur PHP et un peu plus incrémentiels, plus faciles à adapter pour des cas similaires. Ce ne sont que des résumés, souvent liés à plus de variantes ou à des questions et réponses détaillées.
Cartographie statique
/contact
,/about
Raccourcir quelques noms de page en schémas de fichiers internes est le plus simple:
Identifiants numériques
/object/123
L'introduction de raccourcis tels que
http://example.com/article/531
les scripts PHP existants est également facile. L'espace réservé numérique peut simplement être remappé à un$_GET
paramètre:Espaces réservés de style slug
/article/with-some-title-slug
Vous pouvez facilement étendre cette règle pour autoriser les
/article/title-string
espaces réservés:Notez que votre script doit être capable (ou être adapté) de mapper ces titres vers des identifiants de base de données. RewriteRules seul ne peut pas créer ou deviner des informations à partir de rien.
Slugs avec préfixes numériques
/readable/123-plus-title
Par conséquent, vous verrez souvent des
/article/529-title-slug
chemins mixtes utilisés dans la pratique:Maintenant, vous pouvez simplement ignorer de
title=$2
toute façon, car votre script dépendra de toute façon de l'identifiant de la base de données. La-title-slug
décoration d'URL est devenue arbitraire.Uniformité avec les listes alternatives
/foo/…
/bar/…
/baz/…
Si vous avez des règles similaires pour plusieurs chemins de pages virtuelles, vous pouvez les faire correspondre et les compacter avec
|
des listes alternatives. Et encore une fois, réaffectez-les simplement aux paramètres GET internes:Vous pouvez les diviser en plusieurs individus
RewriteRule
si cela devient trop complexe.Distribution des URL associées à différents backends
/date/SWITCH/backend
Une utilisation plus pratique des listes alternatives consiste à mapper les chemins de requête vers des scripts distincts. Par exemple, pour fournir des URL uniformes pour une ancienne et une nouvelle application Web en fonction des dates:
Cela remappe simplement les publications 2009-2011 sur un script, et toutes les autres années implicitement sur un autre gestionnaire. Notez la règle la plus spécifique qui vient en premier . Chaque script peut utiliser différents paramètres GET.
Autres délimiteurs que de simples
/
barres obliques/user-123-name
Vous voyez le plus souvent RewriteRules pour simuler une structure de répertoire virtuel. Mais vous n'êtes pas obligé de ne pas être créatif. Vous pouvez également utiliser des
-
traits d'union pour la segmentation ou la structure.Pour le
/wiki:section:Page_Name
schéma également commun :Parfois, il convient d'alterner entre
/
-delimiters et:
ou.
dans la même règle même. Ou ayez à nouveau deux RewriteRules pour mapper des variantes sur différents scripts.Barre
/
oblique de fin facultative/dir
=/dir/
Lorsque vous optez pour des chemins de style répertoire, vous pouvez le rendre accessible avec et sans /
Maintenant, cela gère à la fois
http://example.com/blog/123
et/blog/123/
. Et l'/?$
approche est facile à ajouter à toute autre RewriteRule.Segments flexibles pour les chemins virtuels
.*/.*/.*/.*
La plupart des règles que vous rencontrerez mappent un ensemble contraint de
/…/
segments de chemin de ressources à des paramètres GET individuels. Certains scripts gèrent cependant un nombre variable d'options . Le moteur de regexp Apache ne permet pas d'en optionnel un nombre arbitraire. Mais vous pouvez facilement le développer vous-même en un bloc de règles:Si vous avez besoin de cinq segments de chemin, copiez ce schéma en cinq règles. Vous pouvez bien sûr utiliser un
[^/]+
espace réservé plus spécifique à chacun. Ici, l'ordre n'est pas aussi important, car aucun des deux ne se chevauche. Donc, avoir en premier les chemins les plus fréquemment utilisés est acceptable.Vous pouvez également utiliser les paramètres de tableau PHP via
?p[]=$1&p[]=$2&p[]=3
une chaîne de requête ici - si votre script les préfère simplement avant la division. (Bien qu'il soit plus courant d'utiliser simplement une règle fourre-tout et de laisser le script lui-même étendre les segments hors de REQUEST_URI.)Voir aussi: Comment transformer mes segments de chemin d'URL en paires clé-valeur de chaîne de requête?
Segments facultatifs
prefix/opt?/.*
Une variante courante consiste à avoir des préfixes facultatifs dans une règle. Cela a généralement du sens si vous avez des chaînes statiques ou des espaces réservés plus contraints autour:
Désormais, le modèle le plus complexe englobe
(?:/([^/])+)?
simplement un groupe non capturant(?:…)
et le rend facultatif)?
. L'espace réservé contenu([^/]+)
serait un modèle de substitution$2
, mais il serait vide s'il n'y a pas de/…/
chemin intermédiaire .Capturez le reste
/prefix/123-capture/…/*/…whatever…
Comme dit précédemment, vous ne voulez pas souvent de modèles de réécriture trop génériques. Il est cependant judicieux de combiner des comparaisons statiques et spécifiques avec un
.*
parfois.Cela a optionnel tous
/…/…/…
les segments de chemin de fin. Ce qui nécessite bien sûr que le script de gestion les sépare, et les paramètres extraits de manière variable lui- même (ce que font les frameworks Web- "MVC" )."Extensions" du fichier de fin
/old/path.HTML
Les URL n'ont pas vraiment d'extensions de fichier. C'est le sujet de toute cette référence (= les URL sont des localisateurs virtuels, pas nécessairement une image directe du système de fichiers). Cependant, si vous aviez un mappage de fichiers 1: 1 auparavant, vous pouvez créer des règles plus simples:
D'autres utilisations courantes sont le remappage de
.html
chemins obsolètes vers des.php
gestionnaires plus récents , ou simplement l'aliasing des noms de répertoire uniquement pour des fichiers individuels (réels / réels).Ping-Pong (redirige et réécrit à l'unisson)
/ugly.html
← →/pretty
Donc, à un moment donné, vous réécrivez vos pages HTML pour ne contenir que de jolis liens, comme indiqué par deceze . En attendant, vous recevrez toujours des demandes pour les anciens chemins, parfois même des signets. Pour contourner ce problème , vous pouvez faire un ping-pong sur les navigateurs pour afficher / établir les nouvelles URL.
Cette astuce courante consiste à envoyer une redirection 30x / Location chaque fois qu'une URL entrante suit le schéma de dénomination obsolète / laid. Les navigateurs demanderont ensuite à nouveau la nouvelle / jolie URL, qui sera ensuite réécrite (uniquement en interne) à l'emplacement d'origine ou au nouvel emplacement.
Notez comment cet exemple utilise simplement
[END]
au lieu de[L]
pour alterner en toute sécurité. Pour les anciennes versions d'Apache 2.2, vous pouvez utiliser d'autres solutions de contournement, en plus de remapper les paramètres de chaîne de requête, par exemple: rediriger moche vers une jolie URL, remapper vers le chemin moche, sans boucles infiniesEspaces ␣dans les motifs
/this+that+
Ce n'est pas si joli dans les barres d'adresse du navigateur, mais vous pouvez utiliser des espaces dans les URL. Pour les modèles de réécriture, utilisez des
\␣
espaces échappés par une barre oblique inverse . Sinon,"
citez tout le motif ou la substitution:Les clients sérialisent les URL avec
+
ou%20
pour des espaces. Pourtant, dans RewriteRules, ils sont interprétés avec des caractères littéraux pour tous les segments de chemin relatifs.Doublons fréquents:
Catch-all pour un script de répartiteur / contrôleur frontal central
Ce qui est souvent utilisé par les frameworks PHP ou les scripts WebCMS / portail. Le partage de chemin réel est alors géré en PHP en utilisant
$_SERVER["REQUEST_URI"]
. Donc, en termes de conception, c'est à peu près l'opposé de la gestion des URL "per mod_rewrite". (Utilisez simplement à laFallBackResource
place.)Supprimer
www.
du nom d'hôteNotez que cela ne copie pas une chaîne de requête, etc.
Voir aussi:
· Réécriture d'URL pour différents protocoles dans .htaccess
· Htaccess générique redirige www vers non-www
· .htaccess - comment forcer "www." de manière générique?
Notez que les combos RewriteCond / RewriteRule peuvent être plus complexes, avec des correspondances (
%1
et$1
) interagissant dans les deux sens même:Manuel Apache - intro mod_rewrite , Copyright 2015 The Apache Software Foundation, AL-2.0
Rediriger vers
HTTPS://
Voir aussi: https://wiki.apache.org/httpd/RewriteHTTPToHTTPS
"Suppression" de l'extension PHP
Voir aussi: Supprimer l'extension .php avec mod_rewrite
Aliaser d'anciens chemins .html vers des scripts .php
Voir: http://httpd.apache.org/docs/2.4/rewrite/remapping.html#backward-compatibility
Réécrire depuis une URL telle que "/ page" vers un script tel que "/index.php/page"
Voir mod_rewrite, php et le fichier .htaccess
Rediriger le sous-domaine vers un dossier
Voir Comment puis-je faire fonctionner mon htaccess (sous-domaines)?
prévalents
.htaccess
piègesMaintenant, prenez ceci avec un grain de sel. Tous les conseils ne peuvent pas être généralisés à tous les contextes. Ceci est juste un simple résumé de quelques écueils bien connus et non évidents:
Activer
mod_rewrite
et.htaccess
Pour utiliser réellement RewriteRules dans les fichiers de configuration par répertoire, vous devez:
Vérifiez que votre serveur est
AllowOverride All
activé . Sinon, vos.htaccess
directives par répertoire seront ignorées et RewriteRules ne fonctionnera pas.Évidemment, ont
mod_rewrite
activé dans votrehttpd.conf
section modules.Ajoutez encore à chaque liste de règles
RewriteEngine On
. Alors que mod_rewrite est implicitement actif dans les sections<VirtualHost>
et<Directory>
, les.htaccess
fichiers par répertoire ont besoin d'être invoqués individuellement.La barre oblique principale
^/
ne correspondra pasVous ne devriez pas démarrer vos
.htaccess
modèles RewriteRule avec^/
normalement:Ceci est souvent vu dans les anciens tutoriels. Et c'était correct pour les anciennes versions d'Apache 1.x. De nos jours, les chemins de requête sont entièrement relatifs aux répertoires dans
.htaccess
RewriteRules. Laissez juste le début/
.· Notez que la barre oblique est toujours correcte dans les
<VirtualHost>
sections. C'est pourquoi vous le voyez souvent^/?
optionnel pour la parité des règles.· Ou lorsque vous utilisez un,
RewriteCond %{REQUEST_URI}
vous correspondez toujours à un leader/
.· Voir aussi Webmaster.SE: Quand la barre oblique principale (/) est-elle nécessaire dans les modèles mod_rewrite?
<IfModule *>
les emballages sont partis!Vous avez probablement vu cela dans de nombreux exemples:
<VirtualHost>
sections - si elle a été associée à une autre option de repli, comme ScriptAliasMatch. (Mais personne ne fait jamais ça)..htaccess
ensembles de règles par défaut avec de nombreux projets open source. Là, il est simplement conçu comme une solution de secours et maintient les URL "laides" par défaut.Cependant, vous ne le souhaitez généralement pas dans vos propres
.htaccess
fichiers.500
erreurs HTTP . Ce qu'il accomplit généralement, c'est honorer vos utilisateurs d'404
erreurs HTTP à la place. (Pas tellement plus convivial si vous y réfléchissez.)Ne pas utiliser
RewriteBase
sauf si nécessaireDe nombreux exemples de copier-coller contiennent une
RewriteBase /
directive. Ce qui se trouve être la valeur implicite par défaut de toute façon. Vous n'avez donc pas vraiment besoin de ça. C'est une solution de contournement pour les schémas de réécriture de VirtualHost sophistiqués et les chemins DOCUMENT_ROOT erronés pour certains hébergeurs partagés.Il est logique de l'utiliser avec des applications Web individuelles dans des sous-répertoires plus profonds. Il peut raccourcir les modèles RewriteRule dans de tels cas. En général, il est préférable de préférer les spécificateurs de chemin relatif dans les ensembles de règles par répertoire.
Voir aussi Comment fonctionne RewriteBase dans .htaccess
Désactiver
MultiViews
lorsque les chemins virtuels se chevauchentLa réécriture d'URL est principalement utilisée pour prendre en charge les chemins entrants virtuels . Généralement vous un seul script répartiteur (
index.php
) ou quelques gestionnaires individuels (articles.php
,blog.php
,wiki.php
, ...). Ce dernier peut entrer en conflit avec des chemins RewriteRule virtuels similaires.Une requête par
/article/123
exemple pourrait mapperarticle.php
avec un/123
PATH_INFO implicitement. Vous devrez soit garder vos règles avec le commonplaceRewriteCond
!-f
+!-d
, et / ou désactiver le support PATH_INFO, ou peut-être simplement désactiverOptions -MultiViews
.Ce qui ne veut pas dire que vous devez toujours le faire . La négociation de contenu n'est qu'un automatisme des ressources virtuelles.
La commande est importante
Voir Tout ce que vous avez toujours voulu savoir sur mod_rewrite si vous ne l'avez pas déjà fait. La combinaison de plusieurs RewriteRules conduit souvent à une interaction. Ce n'est pas quelque chose à empêcher habituellement par
[L]
drapeau, mais un schéma que vous adopterez une fois familiarisé. Vous pouvez re-re-re écriture des chemins virtuels à partir d' une règle à l' autre, jusqu'à ce qu'il atteigne un gestionnaire cible réelle.Pourtant, vous voudrez souvent avoir les règles les plus spécifiques (
/forum/…
modèles de chaîne fixes ou espaces réservés plus restrictifs[^/.]+
) dans les premières règles. Les règles génériques slurp-all (.*
) sont mieux laissées aux dernières . (Une exception est uneRewriteCond -f/-d
garde en tant que bloc principal.)Les feuilles de style et les images ne fonctionnent plus
Lorsque vous introduisez des structures de répertoires virtuels,
/blog/article/123
cela a un impact sur les références de ressources relatives en HTML (comme<img src=mouse.png>
). Ce qui peut être résolu par:href="https://stackoverflow.com/old.html"
ousrc="/logo.png"
<base href="https://stackoverflow.com/index">
dans votre<head>
section HTML . Cela relie implicitement les références relatives à ce qu'elles étaient auparavant.Vous pouvez également créer d'autres règles de réécriture pour les relier
.css
ou les.png
chemins vers leurs emplacements d'origine. Mais c'est à la fois inutile ou entraîne des redirections supplémentaires et entrave la mise en cache.Voir aussi: CSS, JS et les images ne s'affichent pas avec une jolie URL
RewriteConds masque juste une RewriteRule
Une mauvaise interprétation courante est qu'un RewriteCond bloque plusieurs RewriteRules (car elles sont visuellement disposées ensemble):
Ce qui n'est pas le cas par défaut. Vous pouvez les enchaîner à l' aide du
[S=2]
drapeau. Sinon, vous devrez les répéter. Alors que parfois vous pouvez créer une règle primaire "inversée" pour [FIN] le traitement de réécriture tôt.QUERY_STRING exempté des règles de réécriture
Vous ne pouvez pas faire la correspondance
RewriteRule index.php\?x=y
, car mod_rewrite se compare uniquement aux chemins relatifs par défaut. Vous pouvez cependant les faire correspondre séparément via:Voir aussi Comment puis-je faire correspondre les variables de chaîne de requête avec mod_rewrite?
.htaccess
contre.<VirtualHost>
Si vous utilisez RewriteRules dans un fichier de configuration par répertoire, il est inutile de s'inquiéter des performances des regex. Apache conserve les modèles PCRE compilés plus longtemps qu'un processus PHP avec un cadre de routage commun. Pour les sites à fort trafic, vous devriez cependant envisager de déplacer les ensembles de règles dans la configuration du serveur vhost, une fois qu'ils ont été testés au combat.
Dans ce cas, préférez le
^/?
préfixe de séparateur de répertoire optionnel . Cela permet de déplacer librement RewriteRules entre PerDir et les fichiers de configuration du serveur.Chaque fois que quelque chose ne fonctionne pas
Ne vous inquiétez pas.
Comparez
access.log
eterror.log
Souvent, vous pouvez comprendre comment une RewriteRule se comporte mal simplement en regardant votre
error.log
etaccess.log
. Corrélez les temps d'accès pour voir quel chemin de requête est arrivé à l'origine et quel chemin / fichier Apache n'a pas pu résoudre (erreur 404/500).Cela ne vous dit pas quelle RewriteRule est le coupable. Mais les chemins finaux inaccessibles comme
/docroot/21-.itle?index.php
peuvent indiquer où inspecter plus loin. Sinon, désactivez les règles jusqu'à ce que vous obteniez des chemins prévisibles.Activer le RewriteLog
Consultez la documentation Apache RewriteLog . Pour le débogage, vous pouvez l'activer dans les sections vhost:
Cela donne un résumé détaillé de la façon dont les chemins de demande entrants sont modifiés par chaque règle:
Ce qui aide à réduire les règles trop génériques et les incidents regex.
Voir aussi:
· .htaccess ne fonctionne pas (mod_rewrite)
· Conseils pour le débogage des règles de réécriture .htaccess
Avant de poser votre propre question
Comme vous le savez peut-être, Stack Overflow est très approprié pour poser des questions sur mod_rewrite. Faites-les sur le sujet en incluant des recherches et des tentatives antérieures (évitez les réponses redondantes), démontrezregex compréhension, et:
$_SERVER
environnement PHPs s'il s'agit d'une incompatibilité de paramètres.access.log
eterror.log
pour vérifier ce que les règles existantes ont résolu. Mieux encore, unrewrite.log
résumé.Cela permet d'obtenir des réponses plus rapides et plus exactes, et les rend plus utiles aux autres.
Commentez votre
.htaccess
Si vous copiez des exemples de quelque part, veillez à inclure un fichier
# comment and origin link
. Bien que ce ne soit que de mauvaises manières d'omettre l'attribution, cela nuit souvent à la maintenance plus tard. Documentez tout code ou source de didacticiel. En particulier, à l'inverse, vous devriez être d'autant plus intéressé à ne pas les traiter comme des boîtes noires magiques.Ce ne sont pas des URL "SEO"
Avertissement: Juste une bête noire. Vous entendez souvent de jolis schémas de réécriture d'URL appelés liens «SEO» ou autre. Bien que cela soit utile pour rechercher des exemples sur Google, c'est un abus de langage obsolète.
Aucun des moteurs de recherche modernes n'est vraiment perturbé par
.html
et.php
dans les segments de chemin, ou?id=123
les chaînes de requête d'ailleurs. Les moteurs de recherche de vieux, comme AltaVista, ont éviter les sites Web ramper avec des chemins d'accès potentiellement mal assurés. Les robots d'exploration modernes ont souvent même envie de ressources Web profondes.Les «jolies» URLs devraient être utilisées de manière conceptuelle pour rendre les sites Web conviviaux .
/common/tree/nesting
.Cependant, ne sacrifiez pas les exigences uniques du conformisme.
Outils
Il existe divers outils en ligne pour générer des règles de réécriture pour la plupart des URL à paramètres GET:
La plupart du temps, il suffit de générer
[^/]+
des espaces réservés génériques, mais cela suffit probablement pour les sites triviaux.la source
Alternatives à mod_rewrite
De nombreux schémas d'URL virtuelles de base peuvent être réalisés sans utiliser RewriteRules. Apache permet aux scripts PHP d'être appelés sans
.php
extension et avec unPATH_INFO
argument virtuel .Utilisez le PATH_INFO , Luke
De nos jours, il
AcceptPathInfo On
est souvent activé par défaut. Ce qui permet essentiellement à d'.php
autres URL de ressources de porter un argument virtuel:Maintenant, cela
/virtual/path
apparaît dans PHP comme$_SERVER["PATH_INFO"]
où vous pouvez gérer les arguments supplémentaires comme vous le souhaitez.Ce n'est pas aussi pratique que Apache ayant des segments de chemin d'entrée séparée en
$1
,$2
,$3
et de les transmettre comme distinctes les$_GET
variables à PHP. Il s'agit simplement d'émuler de "jolies URL" avec moins d'effort de configuration.Activez MultiViews pour masquer
.php
extensionL'option la plus simple pour éviter également les
.php
"extensions de fichier" dans les URL est d'activer:Cela permet à Apache de sélectionner
article.php
pour les requêtes HTTP en/article
raison du nom de base correspondant. Et cela fonctionne bien avec la fonction PATH_INFO susmentionnée. Vous pouvez donc simplement utiliser des URL commehttp://example.com/article/virtual/title
. Ce qui est logique si vous avez une application Web traditionnelle avec plusieurs points / scripts d'appel PHP.Notez que MultiViews a un objectif différent / plus large. Cela entraîne une très légère baisse des performances, car Apache recherche toujours d'autres fichiers avec des noms de base correspondants. Il est en fait destiné à Content-négociation , si les navigateurs reçoivent la meilleure solution parmi les ressources disponibles ( par exemple
article.en.php
,article.fr.php
,article.jp.mp4
).SetType ou SetHandler pour les
.php
scripts sans extensionUne approche plus dirigée pour éviter de transporter des
.php
suffixes dans les URL consiste à configurer le gestionnaire PHP pour d'autres schémas de fichiers. L'option la plus simple remplace le type de gestionnaire / MIME par défaut via.htaccess
:De cette façon, vous pouvez simplement renommer votre
article.php
script en justearticle
(sans extension), tout en le traitant en tant que script PHP.Maintenant, cela peut avoir des implications sur la sécurité et les performances, car tous les fichiers sans extension seraient désormais acheminés via PHP. Par conséquent, vous pouvez également définir ce comportement pour des fichiers individuels uniquement:
Cela dépend quelque peu de la configuration de votre serveur et du PHP SAPI utilisé. Les alternatives courantes incluent
ForceType application/x-httpd-php
ouAddHandler php5-script
.Autres schémas de réécriture Apache
Parmi ses nombreuses options, Apache fournit des
mod_alias
fonctionnalités - qui fonctionnent parfois aussi bien quemod_rewrite
les RewriteRules. Notez que la plupart de ceux-ci doivent être configurés dans une<VirtualHost>
section cependant, pas dans des.htaccess
fichiers de configuration par répertoire.ScriptAliasMatch
est principalement pour les scripts CGI, mais devrait également fonctionner pour PHP. Il autorise les expressions régulières comme n'importe quel autreRewriteRule
. En fait, c'est peut-être l'option la plus robuste pour configurer un contrôleur frontal fourre-tout.Et une plaine
Alias
aide également avec quelques schémas de réécriture simples.Même une
ErrorDocument
directive simple pourrait être utilisée pour laisser un script PHP gérer les chemins virtuels. Notez qu'il s'agit d'une solution de contournement kludgy, qui interdit tout sauf les requêtes GET et inonde le error.log par définition.Voir http://httpd.apache.org/docs/2.2/urlmapping.html pour plus de conseils.
la source