Référence: mod rewrite, URL rewriting et "pretty links" expliquée
"Assez de liens" est souvent un thème demandé, mais il est rarement pleinement expliqué. mod_rewrite est une façon de faire des "jolis liens", mais c'est complexe et sa syntaxe est très courte, difficile à grok et la documentation suppose un certain niveau de compétence en HTTP. Quelqu'un peut m'expliquer en termes simples comment "liens jolie" travail et comment mod_rewrite peut être utilisé pour les créer?
autres noms communs, alias, termes pour urls propres: URLs RESTful, URLs conviviales, SEO-friendly URLs, les Coups de liquide, MVC url (sans doute un abus de langage)
4 réponses
pour comprendre ce que mod_rewrite vous devez d'abord comprendre comment un serveur web fonctionne. Un serveur web répond à "demandes HTTP . Une requête HTTP à son niveau le plus basique ressemble à ceci:
GET /foo/bar.html HTTP/1.1
C'est la requête simple d'un navigateur à un serveur web demandant le URL /foo/bar.html
de lui. Il est important de souligner qu'il ne demande pas un fichier , il demande juste quelques URL arbitraires. La requête peut aussi ressembler à ceci:
GET /foo/bar?baz=42 HTTP/1.1
c'est tout aussi valable une requête pour une URL, et cela n'a évidemment rien à voir avec les fichiers.
le serveur web est une application écoutant sur un port, acceptant les requêtes HTTP entrant sur ce port et renvoyant une réponse. Un serveur web est entièrement libre de répondre à toute demande en aucune façon qu'il lui fit et de la manière dont vous avez configuré répondre. Cette réponse n'est pas un fichier, c'est un réponse HTTP qui peut ou ne peut pas avoir quoi que ce soit à voir avec des fichiers physiques sur n'importe quel disque. Un serveur web N'a pas besoin D'être Apache, il y a beaucoup d'autres serveurs web qui ne sont que des programmes qui tournent constamment et qui sont attachés à un port qui répond aux requêtes HTTP. Tu peux en écrire une toi-même. Ce paragraphe a été conçu pour vous séparer de toute notion que les URLs directement des fichiers égaux, ce qui est vraiment important pour comprendre. :)
la configuration par défaut de la plupart des serveurs web est de rechercher un fichier qui correspond à l'URL sur le disque dur. Si le document root du serveur est configuré pour, disons, /var/www
, il peut regarder si le fichier /var/www/foo/bar.html
existe et servir de ce si. Si le fichier se termine par ".php" qu'il invoquera le PHP interprète et puis retourner le résultat. Toute cette association est complètement configurable; un fichier ne à mettre fin à ".php" pour le serveur web de l'exécuter par L'intermédiaire de L'interpréteur PHP, et L'URL n'a pas à correspondre à un fichier particulier sur le disque pour que quelque chose se produise.
mod_rewrite est un moyen de réécrire le traitement interne des requêtes. Lorsque le serveur Web reçoit une requête pour L'URL /foo/bar
, vous pouvez réécrire cette URL dans quelque chose d'autre avant que le serveur web va chercher un fichier sur le disque pour le faire correspondre. Simple exemple:
RewriteEngine On
RewriteRule /foo/bar /foo/baz
cette règle dit chaque fois qu'une requête correspond à" /foo/bar", réécrivez-la en"/foo/baz". la requête sera alors traitée comme si /foo/baz
avait été demandée à la place. Cela peut être utilisé pour divers effets, par exemple:
RewriteRule (.*) .html
cette règle correspond à tout ( .*
) et capture it ( (..)
), puis la réécrit en annexe".HTML." En d'autres termes, si /foo/bar
était L'URL demandée, elle sera traitée comme si /foo/bar.html
avait été demandée. Voir http://regular-expressions.info pour plus d'informations sur l'appariement, la capture et le remplacement des expressions régulières.
une autre règle souvent rencontrée est celle-ci:
RewriteRule (.*) index.php?url=
ceci, encore une fois, correspond à n'importe quoi et le réécrit à l'index du fichier.php avec L'URL demandée à l'origine et ajoutée à la requête url
paramètre. C'est-à-dire: pour toutes les requêtes, l'index des fichiers.php est exécuté et ce fichier aura accès à la requête originale dans $_GET['url']
, donc il peut faire tout ce qu'il veut avec elle.
vous mettez principalement ces règles de réécriture dans votre fichier de configuration du serveur web . Apache vous permet également* de les mettre dans un fichier appelé .htaccess
dans votre document root (i.e. à côté de votre .les fichiers php).
* si autorisé par le fichier de configuration principal Apache; c'est facultatif, mais souvent activé.
Ce que mod_rewrite n' pas faire
mod_rewrite ne rend pas magiquement toutes vos URLs "jolies". C'est une erreur courante. Si vous avez ce lien dans votre site web:
<a href="/my/ugly/link.php?is=not&very=pretty">
il n'y a rien que mod_rewrite puisse faire pour rendre ça joli. Dans pour faire un joli lien, il faut:
-
changer le lien vers un joli lien:
<a href="/my/pretty/link">
-
utilisez mod_rewrite sur le serveur pour traiter la requête à L'URL
/my/pretty/link
en utilisant l'une des méthodes décrites ci-dessus.
(on pourrait utiliser mod_substitute
en conjonction pour transformer Les pages HTML et leurs liens contenus. Bien que ce soit généralement plus d'effort que la mise à jour de vos ressources HTML.)
il y a beaucoup de mod_rewrite que vous pouvez faire et des règles d'appariement très complexes que vous pouvez créer, y compris le chaînage de plusieurs réécritures, le remplacement de requêtes vers un service ou une machine complètement différente, la restitution de codes D'état HTTP spécifiques en tant que Réponses, la redirection de requêtes, etc. Il est très puissant et peut être utilisé pour le bien si vous comprenez les Mécanisme de requête-réponse HTTP. Il ne pas automatiquement rendre vos liens jolie.
voir la documentation officielle pour tous les drapeaux et options possibles.
pour développer sur la réponse de deceze , je voulais fournir quelques exemples et une explication d'une autre fonctionnalité mod_rewrite.
tous les exemples ci-dessous supposent que vous avez déjà inclus RewriteEngine On
dans votre fichier .htaccess
.
Exemple De Réécriture
prenons cet exemple:
RewriteRule ^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$ /blog/index.php?id=&title= [NC,L,QSA]
la règle est divisée en 4 sections:
-
RewriteRule
- commence la règle de réécriture -
^blog/([0-9]+)/([A-Za-z0-9-\+]+)/?$
- cela s'appelle le modèle, mais je vais juste l'appeler comme le côté gauche de la règle - ce que vous voulez réécrire de -
blog/index.php?id=&title=
- appelé la substitution, ou le côté droit d'une règle de réécriture-ce que vous voulez réécrire en -
[NC,L,QSA]
sont des drapeaux pour la règle de réécriture, séparés par une virgule, que je vais expliquer plus plus tard
la réécriture ci-dessus vous permettrait de lier à quelque chose comme /blog/1/foo/
et il serait effectivement charger /blog/index.php?id=1&title=foo
.
Gauche de la règle
-
^
indique le début du nom de la page - ainsi il réécriraexample.com/blog/...
mais pasexample.com/foo/blog/...
- chaque série de parenthèses
(…)
représente une expression régulière que nous pouvons capturer en tant que variable dans le côté droit de la règle. Dans cet exemple:- le premier ensemble de crochets -
([0-9]+)
- correspond à une chaîne de caractères d'une longueur minimale de 1 caractère et avec seulement des valeurs numériques (c.-à-d. 0-9). Ceci peut être référencé avecdans le côté droit de la règle
- la deuxième série de parenthèses correspond à une chaîne de caractères d'une longueur minimale de 1 caractère, ne contenant que des caractères alphanumériques (a-Z, A-z, ou 0-9) ou
-
ou+
(note+
est échappé avec un antislash car sans y échapper ce sera exécuté comme un regex répétition Caractère ). Ceci peut être référencé avecdans le côté droit de la règle
- le premier ensemble de crochets -
-
?
signifie que le caractère précédent est facultatif, de sorte que dans ce cas/blog/1/foo/
et/blog/1/foo
seraient réécrits au même endroit -
$
indique que c'est la fin de la chaîne que nous voulons apparier
Drapeaux
ce sont des options qui sont ajoutées entre crochets à la fin de votre règle de réécriture pour spécifier certaines conditions. Encore une fois , il y a beaucoup de différents drapeaux que vous pouvez lire dans la documentation , mais je vais passer en revue certains des drapeaux les plus communs:
NC
aucun cas drapeau 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 cette) seraient appariés.
L
le dernier drapeau 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 lors du traitement de réécriture en cours. Si la règle ne correspond pas, toutes les autres règles s'être essayé dans l'ordre habituel. Si vous ne définissez pas le drapeau L
, toutes les règles suivantes seront appliquées à L'URL réécrite par la suite.
END
depuis Apache 2.4, vous pouvez également utiliser le drapeau [END]
. Une règle d'appariement avec elle complètement terminera le traitement ultérieur d'alias/rewrite. (Alors que le drapeau [L]
peut souvent déclencher un second tour, par exemple lors de la réécriture dans ou hors des sous-répertoires.)
QSA
le drapeau d'ajout de chaîne de requête nous permet de passer en variables supplémentaires à L'URL spécifiée qui sera ajoutée aux paramètres get originaux. Pour notre exemple cela signifie que quelque chose comme /blog/1/foo/?comments=15
chargerait /blog/index.php?id=1&title=foo&comments=15
R
Ce drapeau n'est pas celui que j'ai utilisé dans l'exemple ci-dessus, mais je pensais que vaut la peine de mentionner. Cela vous permet de spécifier une redirection http, avec l'option d'inclure un code d'état (par ex. R=301
). Par exemple, si vous vouliez faire une redirection 301 sur / myblog / to / blog / vous écririez simplement une règle quelque chose comme ceci:
RewriteRule ^/myblog/(*.)$ /blog/ [R=301,QSA,L]
Conditions De Réécriture
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 ya beaucoup de conditions que vous pouvez lire dans la documentation , mais je vais toucher sur un peu d'exemples communs et de les expliquer:
# if the host doesn't start with www. then add it and redirect
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
c'est une pratique très courante, qui préparera votre domaine avec www.
(s'il n'y est pas déjà) et exécutera une redirection 301. Par exemple, charger http://example.com/blog/
vous redirigerait vers http://www.example.com/blog/
# if it cant find the image, try find the image on another domain
RewriteCond %{REQUEST_URI} \.(jpg|jpeg|gif|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)$ http://www.example.com/ [L]
c'est un peu moins courant, mais c'est un bon exemple d'une règle qui ne s'exécute pas si le nom du 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 extension jpg, jpeg, gif ou png (insensible à la casse). -
%{REQUEST_FILENAME} !-f
vérifiera pour voir si le fichier existe sur le serveur courant, et n'exécutera la réécriture que si ce n'est pas le cas -
%{REQUEST_FILENAME} !-d
vérifiera pour voir si le fichier existe sur le serveur courant, et n'exécutera la réécriture que si ce n'est pas le cas - La réécriture va tenter de charger le même fichier sur un autre domaine
Références
Stack Overflow a beaucoup autres ressources considérables pour commencer:
- Serverfault: Tout ce que vous avez toujours voulu savoir sur mod_rewrite
(gardez à l'esprit de supprimer la barre oblique dans^/
préfixes de modèle pour.htaccess
utilisation.) - à Faire et à Ne pas en "15191970920 des fonctionnalités Cachées de mod_rewrite .
- regardez à travers notre mod-rewrite le plus populaire questions et réponses.
- Apache redirection et le remappage guide.
- AskApache ultimate .htaccess guide
- et le mod-rewrite tag wiki références .
Et les nouveaux arrivants-sympathique regex aperçus même:
- Notre regex tag wiki pour une syntaxe recueil.
- Et du court-métrage Apache regex résumé .
- Else regexp.info pour les bases faciles à comprendre.
Souvent utilisée par des espaces réservé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 repli. -
[^/]+
est le plus souvent utilisé pour les segments de chemin. Il correspond à tout sauf à la barre oblique. -
\d+
correspond uniquement à des chaînes numériques. -
\w+
correspond aux caractères alphanumériques. C'est un raccourci pour[A-Za-z0-9_]
. -
[\w\-]+
pour "slug"de style segments du chemin, en utilisant des lettres, des chiffres, des tirets-
et_
-
[\w\-.,]+
ajoute des périodes et des virgules. Préférez un échappé\-
tableau de bord[…]
charclasses. -
\.
dénote une période littérale. Autrement.
en dehors de[…]
est un espace réservé pour tout symbole.
chacun de ces espaces porte habituellement la mention (…)
entre parenthèses comme groupe de capture. Et l'ensemble des marqueurs ^………$
start + end. Citer "patterns" est facultatif.
RewriteRules
les exemples suivants sont PHP-centric et un peu plus incrémental, plus facile à adapter pour des cas similaires. Ils sont juste des résumés, souvent en lien plus de variations ou des questions et réponses détaillées.
-
cartographie statique
/contact
,/about
Raccourcissement d'une page de quelques noms de fichier interne des régimes est la plus simple:
RewriteRule ^contact$ templ/contact.html RewriteRule ^about$ about.php
-
identificateurs numériques
/object/123
introduire des raccourcis comme
http://example.com/article/531
aux scripts PHP existants est également facile. Le paramètre numérique peut simplement être remappé à un paramètre$_GET
:RewriteRule ^article/(\d+)$ article-show.php?id= # └───────────────────────────┘
-
/article/with-some-title-slug
vous pouvez facilement étendre cette règle pour permettre
/article/title-string
placeholders:RewriteRule ^article/([\w-]+)$ article-show.php?title= # └────────────────────────────────┘
Note que de votre script doit être en mesure (ou adapté) à la carte de ces titres dans la base de données-id. Les règles de réécriture seules ne peuvent pas créer ou deviner des informations à partir de rien.
-
limaces avec des préfixes numériques
/readable/123-plus-title
donc vous verrez souvent mixte
/article/529-title-slug
chemins utilisés dans la pratique:RewriteRule ^article/(\d+)-([\w-]+)$ article.php?id=&title= # └───────────────────────────────┘
Maintenant vous ne pouvez pas passer le
title=
de toute façon, parce que votre script se basera généralement sur l'id de la base de données de toute façon. Le-title-slug
est devenu une décoration D'URL arbitraire. -
uniformité avec d'autres listes
/foo/…
/bar/…
/baz/…
si vous avez des règles similaires pour plusieurs chemins de page virtuels, alors vous pouvez les associer et les compacter avec des listes alternatives
|
. Et encore une fois, il suffit de les réassigner aux paramètres internes GET:# ┌─────────────────────────┐ RewriteRule ^(blog|post|user)/(\w+)$ disp.php?type=&id= # └───────────────────────────────────┘
vous pouvez les diviser en 1519580920 "s si cela devient trop complexe.
-
Dispatching liées Url pour différents backends
/date/SWITCH/backend
une utilisation plus pratique des listes alternatives consiste à établir la correspondance entre les chemins de requête et les scripts distincts. Par exemple, pour fournir des URLs uniformes pour une application web plus ancienne et plus récente basée sur les dates:
# ┌─────────────────────────────┐ # │ ┌───────────┼───────────────┐ RewriteRule ^blog/(2009|2010|2011)/([\d-]+)/?$ old/blog.php?date= RewriteRule ^blog/(\d+)/([\d-]+)/?$ modern/blog/index.php?start= # └──────────────────────────────────────┘
il s'agit simplement de remaps 2009-2011 messages sur un script, et toutes les autres années implicitement à un autre gestionnaire. Notez le règle plus spécifique vient en premier . Chacun script pourrait utiliser des params différents.
-
autres délimiteurs que simplement
/
barre oblique
/user-123-name
vous voyez le plus souvent des règles de réécriture pour simuler une structure de répertoire virtuel. Mais tu n'es pas forcée d'être peu créative. Vous pouvez aussi utiliser les traits d'Union
-
pour segmenter ou structurer.RewriteRule ^user-(\d+)$ show.php?what=user&id= # └──────────────────────────────┘ # This could use `(\w+)` alternatively for user names instead of ids.
Pour le commun
/wiki:section:Page_Name
régimeRewriteRule ^wiki:(\w+):(\w+)$ wiki.php?sect=&page= # └─────┼────────────────────┘ │ # └────────────────────────────┘
occasionnellement, il est approprié d'alterner entre
/
- délimiteurs et:
ou.
dans la même règle même. Ou avoir deux règles de réécriture à nouveau pour mapper des variantes sur des scripts différents. -
arrière optionnel
/
barre oblique
/dir
=/dir/
en optant pour des chemins de style répertoire, vous pouvez le rendre accessible avec et sans un final /
RewriteRule ^blog/([\w-]+)/?$ blog/show.php?id= # ┗┛
maintenant, il s'agit à la fois de
http://example.com/blog/123
et/blog/123/
. Et l'approche/?$
est facile à ajouter à n'importe quelle autre règle de réécriture. -
Flexible segments pour les chemins virtuels
.*/.*/.*/.*
la plupart des règles que vous rencontrerez map Un ensemble limité de segments de chemin de ressources
/…/
pour obtenir des paramètres individuels. Certains scripts gèrent un nombre variable d'options cependant. Le moteur regexp D'Apache ne permet pas d'en optionaliser un nombre arbitraire. Mais vous pouvez facilement l'étendre dans un bloc de règles vous-même:Rewriterule ^(\w+)/?$ in.php?a= Rewriterule ^(\w+)/(\w+)/?$ in.php?a=&b= Rewriterule ^(\w+)/(\w+)/(\w+)/?$ in.php?a=&b=&c= # └─────┴─────┴───────────────────┴────┴────┘
si vous avez besoin de jusqu'à cinq segments de chemin, alors copiez ce schéma en cinq règles. Vous pouvez bien sûr utiliser un placeholder plus spécifique
[^/]+
chacun. Ici, l'ordre n'est pas important, ni chevauchements. Donc avoir les chemins Les plus fréquemment utilisés en premier est correct.alternativement vous pouvez utiliser les paramètres du tableau de PHPs via la chaîne de requête
?p[]=&p[]=&p[]=3
ici - si votre script Les préfère simplement pré-split. (Même si c'est plus commune juste utilisez une règle fourre-tout, et laissez le script lui-même étendre les segments à partir du REQUEST_URI.)voir aussi: comment transformer mes segments de chemin D'URL en paires clé-valeur de chaîne de requête?
-
segments optionnels
prefix/opt?/.*
une variante courante est d'avoir des préfixes optionnels à l'intérieur une règle. Cela a généralement du sens si vous avez des chaînes statiques ou des espaces plus restreints autour de:
RewriteRule ^(\w+)(?:/([^/]+))?/(\w+)$ ?main=&opt=&suffix=
maintenant le motif plus complexe
(?:/([^/])+)?
il enveloppe simplement un non-capturing(?:…)
groupe, et le rend facultatif)?
. Le contenu de l' le paramètre([^/]+)
serait un modèle de substitution, mais il serait vide s'il n'y avait pas de chemin
/…/
moyen. -
capturer le reste
/prefix/123-capture/…/*/…whatever…
comme dit plus haut, vous ne voulez pas souvent des modèles de réécriture trop génériques. Il est toutefois logique de combiner parfois des comparaisons statiques et spécifiques avec un
.*
.RewriteRule ^(specific)/prefix/(\d+)(/.*)?$ speci.php?id=&otherparams=
cette option permet de choisir n'importe quel segment de
/…/…/…
. Ce qui nécessite bien sûr la manipulation script pour les séparer, et variabl-identifier paramètres extraits lui-même (ce qui est ce que Web - "MVC" cadres font). -
extension de fichier arrière""
Les URLs
/old/path.HTML
n'ont pas vraiment d'extension de fichier. Qui est ce que cette référence entière est au sujet (=URLs sont des locators virtuels, pas nécessairement un direct image du système de fichiers). Cependant, si vous avez déjà eu un mappage de fichier 1:1, vous can craft simpler rules:
RewriteRule ^styles/([\w\.\-]+)\.css$ sass-cache.php?old_fn_base= RewriteRule ^images/([\w\.\-]+)\.gif$ png-converter.php?load_from=
D'autres utilisations communes sont la refonte obsolète
.html
chemins vers les nouveaux.php
handlers, ou tout simplement l'aliasing des noms de répertoires seulement pour les fichiers individuels (réels/réels). -
Ping-Pong (les redirections et les réécrit à l'unisson)
/ugly.html
←→/pretty
donc à un moment donné vous réécrivez vos pages HTML pour ne porter que de jolis liens, comme décrit par deceze . Pendant ce temps, vous recevrez toujours des demandes pour les chemins Vieux , parfois même à partir de signets. Comme solution , vous pouvez ping-pong navigateurs pour afficher / établir la nouvelle Url.
Cette astuce courante consiste à envoyer un 30x / Location rediriger chaque fois qu'une URL entrante suit le schéma de nommage obsolète/laid. Les navigateurs rerequest la nouvelle/jolie URL, qui est ensuite réécrite (juste en interne) à l'emplacement original ou Nouveau.
# redirect browser for old/ugly incoming paths RewriteRule ^old/teams\.html$ /teams [R=301,QSA,END] # internally remap already-pretty incoming request RewriteRule ^teams$ teams.php [QSA,END]
notez comment cet exemple utilise simplement
[END]
au lieu de[L]
pour alterner en toute sécurité. Pour les versions plus anciennes D'Apache 2.2, vous pouvez utiliser autres solutions de rechange, en plus de refaire paramètres de chaîne de requête par exemple: Rediriger laid URL jolie, remap retour vers le truand chemin, sans les boucles infinies -
espaces e-mail in patterns
/this+that+
ce n'est pas que jolie dans les barres d'adresse du navigateur, mais vous pouvez utilisez des espaces dans les URLs. Pour les modèles de réécriture utiliser backslash-échappée
\␣
espaces. Autrement juste"
- citer le modèle entier ou la substitution:RewriteRule "^this [\w ]+/(.*)$" "index.php?id=" [L]
les clients sérialisent les URLs avec
+
ou%20
pour les espaces. Pourtant, dans les règles de réécriture, ils sont interprétés avec des caractères littéraux pour tous les segments de chemin relatif.
duplicata fréquents:
-
Fourre-tout pour un répartiteur central / avant-contrôleur de script
RewriteCond %{REQUEST_URI} !-f RewriteCond %{REQUEST_URI} !-d RewriteRule ^.*$ index.php [L]
qui est souvent utilisé par les cadres de PHP ou webcms / scripts de portail. La séparation du chemin réel est alors traitée en PHP en utilisant
$_SERVER["REQUEST_URI"]
. Donc, sur le plan conceptuel, c'est à peu près le contraire de la gestion D'URL "par mod_rewrite". (Il suffit d'utiliserFallBackResource
à la place.) -
Supprimer
www.
du nom d'hôtenotez que cela ne copie pas une chaîne de requête le long, etc.
# ┌──────────┐ RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] │ RewriteRule ^(.*)$ http://%1/ [R=301,L] │ # ↓ └───┼────────────┘ # └───────────────┘
Voir aussi:
· la réécriture d'URL pour les différents protocoles .htaccess
· htaccess Generic redirect www to non-www
· .htaccess - comment forcer "www."de façon générique?notez que les combinaisons RewriteCond/RewriteRule peuvent être plus complexes, avec des correspondances (
%1
et) interagissant dans les deux sens, même:
Apache manual-mod_rewrite intro , Copyright 2015 the Apache Software Foundation, AL-2.0 -
Rediriger
HTTPS://
RewriteCond %{SERVER_PORT} 80 RewriteRule ^(.*)$ https://example.com/ [R,L]
Voir aussi: https://wiki.apache.org/httpd/RewriteHTTPToHTTPS
-
"Supprimer" l'extension PHP
RewriteCond %{REQUEST_FILENAME}.php -f RewriteRule ^(.+)$ .php [L] # or [END]
Voir aussi: supprimer le .extension php avec mod_rewrite
-
Aliasing old .chemins html de. scripts php
voir: http://httpd.apache.org/docs/2.4/rewrite/remapping.html#backward-compatibility
-
Réécriture d'URL "/page" à un script tel que "/index.php / page"
-
Rediriger un sous-domaine vers un dossier
Voir Comment puis-je obtenir mon htaccess de travail (sous-domaines)?
prévalent .htaccess
pitfalls
prenez ceci avec un grain de sel. Pas chaque conseiller peut être généralisée à tous les contextes. Il ne s'agit là que d'un simple résumé des pierres d'achoppement bien connues et peu évidentes:
-
Activer
mod_rewrite
et.htaccess
pour utiliser réellement les règles de réécriture dans les fichiers de configuration par répertoire, vous devez:
-
vérifiez que votre serveur a
AllowOverride All
activé . Sinon, vos directives.htaccess
par répertoire seront ignorées, et les règles de réécriture ne fonctionneront pas. -
évidemment ont
mod_rewrite
activé dans votrehttpd.conf
section modules. -
préparez chaque liste de règles avec
RewriteEngine On
still. Alors que mod_rewrite est implicitement actif dans les sections<VirtualHost>
et<Directory>
, le répertoire.htaccess
fichiers individuellement convoqués.
-
-
slash
^/
ne correspond pasvous ne devriez pas commencer votre
.htaccess
RewriteRule modèles avec^/
normalement:RewriteRule ^/article/\d+$ … ↑
cela se voit souvent dans de vieux tutoriels. Et elle était correcte pour L'ancienne Apache 1.X versions. De nos jours, les chemins de requête sont commodément entièrement directory-relative dans
"15191810920 · * notez que la barre oblique avant est toujours correcte dans.htaccess
RewriteRules. Il suffit de laisser le/
en tête.<VirtualHost>
sections cependant. C'est pourquoi vous le voyez souvent^/?
optionalisé pour la parité de règles.
· Ou en utilisant unRewriteCond %{REQUEST_URI}
, vous correspondriez quand même à un/
.
· Voir aussi Webmaster.SE: Quand le slash principal (/) est-il nécessaire dans les patterns mod_rewrite? -
<IfModule *>
wrappers vas-t'en!vous avez probablement vu dans de nombreux exemples:
<IfModule mod_rewrite.c> Rewrite… </IfModule>
- Il ne faire sens
<VirtualHost>
sections - si elle était combinée avec une autre option de secours, tels que ScriptAliasMatch. (Mais personne ne l'a jamais fait). - et il est couramment distribué pour les règles par défaut
.htaccess
avec de nombreux projets open source. Là, il est juste signifié comme repli, et garde" laid " URLs de travail comme défaut.
Toutefois vous ne veulent pas que d'habitude dans votre propre "1519260920 de fichiers".
- premièrement, mod_rewrite ne se désengage pas de façon aléatoire. (Si c'était le cas, vous auriez plus de problèmes).
- S'il était vraiment désactivé, vos règles de réécriture ne fonctionneraient toujours pas de toute façon.
- il est destiné à prévenir les erreurs HTTP
500
. Ce qu'il accomplit habituellement est en train d'honorer vos utilisateurs avec des erreurs HTTP404
à la place. (Pas tellement plus convivial si vous y pensez.) - pratiquement, il supprime simplement les entrées de journal plus utiles, ou les messages de notification de serveur. Vous seriez aucun le plus sage quant à la raison pour laquelle vos règles de réécriture ne fonctionnent jamais.
ce qui semble séduisant comme garantie généralisée, se révèle souvent être un obstacle dans la pratique.
- Il ne faire sens
-
Ne pas utiliser
RewriteBase
si nécessairede nombreux exemples de copier + coller contiennent une directive
RewriteBase /
. Ce qui se trouve être le défaut implicite de toute façon. Si vous n'avez pas réellement besoin de cela. Il s'agit d'une solution de contournement pour les schémas de réécriture virtuelshost de fantaisie, et des chemins DOCUMENT_ROOT erronés pour certains serveurs partagés.Il est logique de l'utiliser avec applications web individuelles dans des sous-répertoires plus profonds. Dans de tels cas, il peut raccourcir les patterns RewriteRule. 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 RewriteBase de travail .htaccess
-
Désactiver
MultiViews
quand les chemins virtuels chevauchementréécriture D'URL est principalement utilisé pour soutenir virtuel entrants chemins. Généralement, vous n'avez qu'un seul script de répartiteur (
index.php
) ou quelques manipulateurs individuels(articles.php
,blog.php
,wiki.php
, ...). Ce dernier pourrait heurter avec des chemins de réécriture virtuels similaires.une demande pour
/article/123
par exemple pourrait correspondre àarticle.php
avec un/123
PATH_INFO implicitement. Vous auriez soit à garder vos règles alors avec le banaleRewriteCond
!-f
+!-d
, et / ou désactiver le support PATH_INFO, ou peut-être simplement désactiverOptions -MultiViews
.ce qui ne veut pas dire qu'on doit toujours à . 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à. La combinaison de plusieurs règles de réécriture conduit souvent à une interaction. Ce n'est pas quelque chose à empêcher habituellement par
[L]
drapeau, mais un schéma que vous embrasserez une fois versé. Vous can re-re-re write chemins virtuels d'une règle à l'autre, jusqu'à ce qu'il atteigne un gestionnaire de cible réel.Encore vous serais souvent voulez avoir le plus de règles spécifiques (fixe chaîne
/forum/…
modèles", ou plus restrictive des espaces réservés[^/.]+
) dans le début les règles. Les règles génériques slurp-all (.*
) sont mieux laissées aux règles postérieures . (Une exception est un gardeRewriteCond -f/-d
comme bloc primaire.) -
feuilles de style et les images d'arrêt de travail
quand vous introduisez les structures de répertoires virtuels
/blog/article/123
ceci répercussions références relatives aux ressources en HTML (comme<img src=mouse.png>
). Qui peut être résolu par:- utiliser uniquement le serveur-références absolues
href="/old.html"
ousrc="/logo.png"
- souvent simplement en ajoutant
<base href="/index">
dans votre section HTML<head>
. Cela rebinde implicitement les références relatives à ce qu'elles étaient avant.
vous pouvez alternativement rédiger D'autres règles de réécriture à rebranchez
.css
ou.png
vers leur emplacement 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 de jolies url
- utiliser uniquement le serveur-références absolues
-
RewriteConds juste un masque RewriteRule
une mauvaise interprétation courante est qu'une directive RewriteCond bloque plusieurs règles RewriteRules (parce qu'elles sont visuellement disposés ensemble):
RewriteCond %{SERVER_NAME} localhost RewriteRule ^secret admin/tools.php RewriteRule ^hidden sqladmin.cgi
ce qui n'est pas par défaut. Vous pouvez les enchaîner en utilisant le drapeau
[S=2]
. Autre chose que vous aurez à les répéter. Alors que parfois vous pouvez craft une règle primaire "inversée" pour [END] le traitement de réécriture tôt. -
QUERY_STRING exempt from RewriteRules
Vous ne pouvez pas correspondre à
RewriteRule index.php\?x=y
, parce que mod_rewrite compare juste contre les chemins relatifs par défaut. Vous pouvez les apparier séparément cependant via:RewriteCond %{QUERY_STRING} \b(?:param)=([^&]+)(?:&|$) RewriteRule ^add/(.+)$ add/%1/ # ←──﹪₁──┘
Voir aussi Comment puis-je match des variables chaîne de requête avec le mod_rewrite?
-
.htaccess
vs.<VirtualHost>
si vous utilisez RewriteRules dans un fichier de configuration par répertoire, alors s'inquiéter des performances de regex est inutile. Apache conserve compiler Les patrons PCRE sont plus longs qu'un processus PHP avec un cadre de routage commun. Pour les sites à fort trafic, vous devriez envisager déplacement des règles dans la configuration du serveur vhost, une fois qu'elles ont été testées.
dans ce cas, préférer le préfixe optionnel du séparateur de répertoires
^/?
. Cela permet de déplacer librement les règles de réécriture entre PerDir et le serveur les fichiers de configuration. -
Chaque fois que quelque chose de ne fonctionne pas
ne vous inquiétez pas.
-
comparer
access.log
eterror.log
souvent, vous pouvez comprendre comment une règle RewriteRule se comporte mal en regardant votre
error.log
etaccess.log
. Corrélez les temps d'accès pour voir quel chemin de requête est entré à l'origine, et quel chemin/fichier Apache n'a pas pu résoudre (erreur 404/500).cela ne vous dit pas qui réécrit est le coupable. Mais des chemins finals inaccessibles comme
/docroot/21-.itle?index.php
peuvent donner où inspecter plus loin. Sinon, désactivez les règles jusqu'à ce que vous ayez des chemins prévisibles. -
activer le RewriteLog
voir Apache RewriteLog docs. Pour le débogage, vous pouvez l'activer dans les sections vhost:
# Apache 2.2 RewriteLogLevel 5 RewriteLog /tmp/rewrite.log # Apache 2.4 LogLevel alert rewrite:trace5 #ErrorLog /tmp/rewrite.log
qui fournit un résumé détaillé de la façon dont les chemins de requête entrants sont modifiés par chaque règle:
[..] applying pattern '^test_.*$' to uri 'index.php' [..] strip per-dir prefix: /srv/www/vhosts/hc-profi/index.php -> index.php [..] applying pattern '^index\.php$' to uri 'index.php'
qui aide à réduire les règles trop génériques et les accidents regex.
Voir aussi:
· .htaccess ne fonctionne pas (mod_rewrite)
· Conseils pour le débogage .htaccess de réécrire les règles -
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 thème en incluant les recherches et les tentatives antérieures (éviter les réponses redondantes), démontrer de base regex comprendre, et:
- comprend full exemples D'URL d'entrée, chemins cibles réécrits, votre véritable structure de répertoire.
- l'ensemble complet de règles de réécriture, mais aussi singularise le présumé défectueux.
- Apache et les versions de PHP, type de système d'exploitation, système de fichiers, DOCUMENT_ROOT, et PHPs
$_SERVER
environnement si il s'agit d'un paramètre de décalage. - Un extrait de votre
access.log
eterror.log
pour vérifier ce à quoi les règles existantes ont résolu. Mieux encore, unrewrite.log
résumé.
cela permet des réponses plus rapides et plus précises, et les rend plus utiles aux autres.
-
-
votre Commentaire
.htaccess
si vous copiez des exemples quelque part, veillez à inclure un
# comment and origin link
. Alors que c'est de mauvaises manières d'omettre attribution, Cela fait souvent très mal à l'entretien plus tard. Documentez n'importe quel code ou source de tutoriel. En particulier, tout en unversed vous devriez être d'autant plus intéressé à ne pas les traiter comme des boîtes noires magiques. -
ce n'est pas "SEO" - URLs
Avertissement: Juste une bête noire. vous entendez souvent de jolies URL réécrire des schémas appelés liens" SEO " ou quelque chose. Bien que cela soit utile pour googler des exemples, il est daté d'abus de langage.
aucun des moteurs de recherche modernes ne sont vraiment dérangés par
.html
et.php
dans les segments de chemin, ou?id=123
chaînes d'interrogation pour cette matière. Les moteurs de recherche de vieux, tels que AltaVista, did éviter de ramper des sites Web avec des chemins d'accès potentiellement Ambigus. Les chenilles modernes sont souvent même en manque de ressources Web profondes.Ce "joli" Url conceptuellement être utilisé pour est la fabrication de sites Web convivial ".
- ayant des schémas de ressources lisibles et évidents.
- Assurer les Url sont de longue durée (AKA permaliens ).
- Fournir de la visibilité via les
/common/tree/nesting
.
cependant, ne sacrifiez pas les exigences uniques pour conformisme.
outils
il existe divers outils en ligne pour générer des règles de réécriture pour la plupart des URLs GET-parameterish:
- http://www.generateit.net/mod-rewrite/index.php
- http://www.ipdistance.com/mod_rewrite.php
- http://webtools.live2support.com/misc_rewrite.php
la plupart du temps juste sortie [^/]+
emplacements génériques, mais suffices probablement pour les sites triviaux.
solutions de rechange " mod_rewrite
de nombreux schémas D'URL virtuelle de base peuvent être obtenus sans utiliser les règles de réécriture. Apache permet aux scripts PHP d'être invoqués sans extension .php
, et avec un argument virtuel PATH_INFO
.
-
utilisez le PATH_INFO , Luke
de nos jours
AcceptPathInfo On
est souvent activé par défaut. Ce qui en gros permet à.php
et à D'autres URL de ressources de porter un argument virtuel:http://example.com/script.php/virtual/path
maintenant ce
/virtual/path
apparaît en PHP comme$_SERVER["PATH_INFO"]
où vous pouvez gérer tous les arguments supplémentaires comme vous voulez.ce n'est pas aussi pratique que D'avoir Apache séparer les segments de chemin d'entrée en
,
,
et les passer en tant que variables distinctes
$_GET
à PHP. C'est simplement émuler "pretty URLs" avec moins d'effort de configuration. -
Activer MultiViews pour masquer la
.php
extensionl'option la plus simple pour également éviter
.php
" extensions de fichier "dans les URLs est activer:Options +MultiViews
Apache sélectionne
article.php
pour les requêtes HTTP sur/article
en raison du nom de base correspondant. Et cela fonctionne bien avec le susmentionnés PATH_INFO fonctionnalité. Vous pouvez donc simplement utiliser des URLs commehttp://example.com/article/virtual/title
. Ce qui a du sens si vous avez une application web traditionnelle avec plusieurs points D'invocation/scripts PHP.notez que MultiViews a un but différent/plus large cependant. Il encourt une pénalité de performance très mineure , car Apache cherche toujours d'autres fichiers avec des noms de base correspondants. Il est en fait destiné à Content-Negotiation , donc les navigateurs reçoivent la meilleure alternative parmi les ressources disponibles (telles que
article.en.php
,article.fr.php
,article.jp.mp4
). -
SetType ou SetHandler pour extensionless
.php
scriptsune approche plus directe pour éviter de transporter des suffixes
.php
dans les URLs est configurer le gestionnaire PHP pour d'autres schémas de fichiers. L'option la plus simple est d'annuler le type MIME/handler par défaut. via.htaccess
:DefaultType application/x-httpd-php
de cette façon, vous pouvez simplement renommer votre script
article.php
en justearticle
(sans extension), mais tout de même le faire traiter comme un script PHP.maintenant cela peut avoir des implications de sécurité et de performance, parce que tous les fichiers sans extension seraient acheminés par PHP maintenant. Par conséquent, vous pouvez également définir ce comportement pour les fichiers individuels seulement:
<Files article> SetHandler application/x-httpd-php # or SetType </Files>
c'est cela dépend un peu de la configuration de votre serveur et de L'utilisation de PHP SAPI. Les variantes les plus courantes sont
ForceType application/x-httpd-php
ouAddHandler php5-script
.à nouveau, notez que de tels paramètres se propagent d'un
.htaccess
aux sous-dossiers. Vous devez toujours désactiver l'exécution du script (SetHandler None
etOptions -Exec
ouphp_flag engine off
etc.) pour les ressources statiques, et de télécharger des répertoires/ etc. -
Autres Apaches programmes de réécriture 1519500920"
parmi ses nombreuses options, Apache fournit des fonctionnalités
mod_alias
- qui fonctionnent parfois aussi bien quemod_rewrite
s RewriteRules. Notez que la plupart de ceux-ci doivent être configurés dans une section<VirtualHost>
cependant, pas dans les fichiers de configuration.htaccess
par répertoire.-
ScriptAliasMatch
est principalement pour les scripts CGI, mais devrait également fonctionner pour PHP. Il permet regexps tout comme toutRewriteRule
. En fait, c'est peut-être l'option la plus robuste pour configurer une manette avant fourre-tout. -
Et un simple
Alias
permet avec un simple réécriture de systèmes. -
même une directive simple "15191160920
ErrorDocument
pourrait être utilisée pour laisser un script PHP gérer des chemins virtuels. Notez que c'est une solution de contournement toutefois encombrants, interdit tout sauf obtenir des requêtes, et inonde l'erreur.journal, par définition.
voir http://httpd.apache.org/docs/2.2/urlmapping.html pour d'autres conseils.
-