Comment fonctionne réellement mod_rewrite. Provision pour continuer

Как на самом деле работает mod_rewrite. Пособие для продолжающих

Cet article est issu des idées de formation avancée de nos employés appuient le travail avec mod_rewrite. La pratique a montré que, après avoir étudié disponible dans un grand nombre de manuels scolaires dans le support technique russe bonne décision tâches de routine donnés, mais une compilation indépendante des règles est par essais et beaucoup d'erreur. Le problème est que, pour une bonne compréhension de la nécessité d'étudier les documents originaux en anglais mod_rewrite, puis - soit plus de précisions ou heures expériences RewriteLog.

L'article décrit les travaux mécanisme mod_rewrite. Comprendre comment cela fonctionne vous permet de réaliser clairement l'effet de chaque directive, et une idée claire de ce qui se passe dans un moment donné dans un mod_rewrite dans les directives de traitement.

Je suppose que le lecteur est déjà familier avec ce que le mod_rewrite, et je ne vais pas décrire ses fondations, qui sont faciles à trouver sur Internet. Il convient également de noter que l'article met en évidence le travail mod_rewrite utilisant ses directives dans le fichier .htaccess. Différences au travail dans le cadre de figurant à la fin.

Donc, vous avez appris le mod_rewrite, se sont élevées à plusieurs RewriteRule et a dû faire face à la redirection infinie avec le cas où une règle pour une raison quelconque ne pas attraper votre demande, ainsi que imprévisible groupe de règles de travail quand une règle de demande de changement soudain subséquente, soigneusement préparée par les règles précédentes.

Ce qui fonctionne RewriteRule

Le premier RewriteRule est passé le chemin de l'endroit où le .htaccess, le fichier demandé. Cette ligne ne sera pas commencer par "/". RewriteRule Après résultat de la transformation précédente transmise.

Afin de bien comprendre comment le RewriteRule, vous devez d' abord déterminer ce que cela fonctionne. Considérons, comme Apache obtient la chaîne qui a été initialement transmis à l'RewriteRule de traitement en .htaccess.

Dès que vous commencez à travailler avec le mod_rewrite, il est logique de supposer qu'il fonctionne avec des liens. Toutefois, dans le cas de l'utilisation mod_rewrite .htaccess non. En fait RewriteRule aucun lien est passé, et le chemin vers le fichier demandé.

En raison de l'architecture interne d'Apache dans le moment où l'opération entre .htaccess, mod_rewrite peut gérer seulement à travers le fichier à traiter. Cela est dû au fait que, avant la demande de transfert est déjà dans mod_rewrite pourrait changer d'autres modules (par exemple, mod_alias), et le chemin final vers le fichier sur le site ne peut pas correspondre à la référence originale. Si mod_rewrite a travaillé avec le lien d'origine, il perturberait le fonctionnement des modules qui ont changé la demande de lui.

Par conséquent, mod_rewrite est transféré vers le chemin absolu du fichier à traiter. mod_rewrite connaît également la voie à .htaccess, qui abrite la règle RewriteRule. Afin de rendre le chemin vers le fichier est quelque chose comme un lien, qui prévoit d'exploiter un développeur de site, le mod_rewrite coupe une partie du chemin absolu vers le fichier .htaccess.

Donc, ceci est le chemin qui coupa le chemin vers le .htaccess, a passé le premier RewriteRule. Par exemple:

  • Requête: http://example.com/templates/silver/images/logo.gif
  • DocumentRoot: /var/www/example.com
  • Le chemin vers le fichier: /var/www/example.com/templates/silver/images/logo.gif
  • .htaccess est en: /var/www/example.com/templates/.htaccess
  • Le premier RewriteRule sera transféré: argent / images / logo.gif
  • Remarque: «templates /» également coupés.
Как на самом деле работает mod_rewrite. Пособие для продолжающих

Le chemin vers le .htaccess est coupé avec une barre oblique. Ceci est une conséquence de: une chaîne qui a été initialement transmis à l'RewriteRule de traitement ne commence jamais par un "/".

Il est important de se rappeler que cela fait RewriteRule. Il ne gère pas le nom du site, les arguments qui sont passés au script, et le lien ne traite pas tout cela, si le .htaccess est pas hébergé dans la racine du site. Toutes ces offres RewriteCond, qui touchent brièvement plus tard. donc:

# работать не будет - правило начинается со /
RewriteRule ^/index.php$ /my-index.php

# работать не будет - название сайта не анализируется RewriteRule
RewriteRule ^example.com/.* http://www.example.com

# работать не будет - аргументы ссылки не попадают в RewriteRule
RewriteRule index.php\?newspage=([0-9]+) news.php?page=$1
# работать не будет - правило начинается со /
RewriteRule ^/index.php$ /my-index.php

# работать не будет - название сайта не анализируется RewriteRule
RewriteRule ^example.com/.* http://www.example.com

# работать не будет - аргументы ссылки не попадают в RewriteRule
RewriteRule index.php\?newspage=([0-9]+) news.php?page=$1
0-9] +) news.php? Page = $ # работать не будет - правило начинается со /
RewriteRule ^/index.php$ /my-index.php

# работать не будет - название сайта не анализируется RewriteRule
RewriteRule ^example.com/.* http://www.example.com

# работать не будет - аргументы ссылки не попадают в RewriteRule
RewriteRule index.php\?newspage=([0-9]+) news.php?page=$1
# Будет работать только если .htaccess находится там же, где находится папка templates,
# например, в корне сайта. То есть, если .htaccess находится в templates/.htaccess , правило
# работать НЕ БУДЕТ, потому что mod_rewrite отрежет путь до .htaccess и на вход RewriteRule
# строка попадет уже без "templates/"
RewriteRule ^templates/common/yandex-money.gif$ templates/shared/yad.gif
# Будет работать только если .htaccess находится там же, где находится папка templates,
# например, в корне сайта. То есть, если .htaccess находится в templates/.htaccess , правило
# работать НЕ БУДЕТ, потому что mod_rewrite отрежет путь до .htaccess и на вход RewriteRule
# строка попадет уже без "templates/"
RewriteRule ^templates/common/yandex-money.gif$ templates/shared/yad.gif

Au début de l'utilisation de mod_rewrite, je vous recommande de travailler avec lui que dans le .htaccess dans la racine du site. Cela facilitera plus de contrôle sur son travail.

Ce qui fonctionne RewriteRule, nous comprenons. Maintenant , nous allons voir comment cela fonctionne.

Comment fonctionne RewriteRule

RewriteRule convertit simplement la chaîne en conformité avec les expressions régulières et tous. RewriteRule fonctionne avec de la ficelle, et non en référence au fichier ou par.

Comme nous l'avons expliqué ci-dessus, l'entrée à RewriteRule obtient le chemin du fichier .htaccess à la recherche. Le moyen le plus pratique est maintenant ignorer les chemins et les liens, et d'envisager quelque chose avec qui exploite le RewriteRule, comme une chaîne simple. Cette ligne est transférée de la RewriteRule à RewriteRule, muter, si une partie du travail de RewriteRule.

En termes généraux, si l'on exclut les difficultés avec l'aide de drapeaux (dont certains seront discutés ci-dessous) et les difficultés rencontrées dans la compilation des expressions régulières (que nous allons presque pas toucher dans cet article), le RewriteRule fonctionne très simplement.

  1. Nous avons pris la ligne.
  2. Comparez cela avec une expression régulière dans le premier argument.
  3. S'il y a une coïncidence - ont remplacé la chaîne entière du deuxième argument.
  4. Passez la chaîne à la RewriteRule suivante.

Ici, en général, et tout. Pour montrer que la RewriteRule fonctionne exactement de la chaîne, prenons l'exemple fantastique suivante:

# Запрос: http://mysite.com/info.html
# В первый RewriteRule попадет "info.html"

# Преобразовываем запрос в произвольную строку.
RewriteRule ^info.html$ "I saw a turtle in the hole. And it was dancing rock-n-roll. And it was smiling. All in all, it was a very funny doll."

# "info.html" -> "I saw a turtle..."

# Заменяем эту строку на внешнюю ссылку.
RewriteRule turtle https://example.com/information/index.html

# "I saw a turtle..." -> "https://example.com/information/index.html"

# Заменяем имя сайта!
RewriteRule ^(.*)example.com(.*)$ $1example.org$2

# "https://example.com/information/index.html" -> "https://example.org/information/index.html"

# Заменяем протокол!
RewriteRule ^https :( .*)$ ftp:$1

# "https://example.org/information/index.html" -> "ftp://example.org/information/index.html"

# Заменяем конечную ссылку.
RewriteRule ^(.*)/index.html$ $1/main.php

# "ftp://example.org/information/index.html" -> "ftp://example.org/information/main.php"

Comme vous pouvez le voir, le RewriteRule est comme beaucoup de travail - il transforme simplement une chaîne en fonction de demander à ses arguments. Si vous voulez, vous pouvez stocker toute chaîne dans les ensembles de données peuvent même de morpion sur RewriteRule écriture si vous le souhaitez, la persévérance et une bonne connaissance des expressions régulières.

Ici, vous devez faire un point: même RewriteRule et fonctionne avec une ligne claire, il est toujours axé sur le travail avec des références. Par conséquent, il sera d'une manière spéciale pour répondre aux lignes commençant par «https: //» "?" Ou analogues (rappelez-vous que nous voulions faire une redirection externe) et le symbole (Considère les caractères suivants sont des arguments qui doivent être substitut à la demande). Maintenant, cependant, nous ne nous soucions pas - il est important de comprendre que le RewriteRule a pas de magie - il faut juste une chaîne et changer la façon dont vous l'avez dit. redirections externes et arguments seront examinés plus tard dans l'article, il y a aussi beaucoup de choses à parler.

Après toutes les modifications sont prises et exécutées le dernier RewriteRule, entrera en vigueur RewriteBase.

Quel est le RewriteBase

Si vous trouvez que, après la demande de transformation est relative et diffère de l'original, RewriteBase s'ajouter à lui sur la gauche. Il est nécessaire de préciser dans le RewriteBase .htaccess. Sa valeur - le chemin de la racine du site à .htaccess. RewriteBase effectuée seulement après que tous les RewriteRule, mais pas entre eux.

Nous avons déjà mentionné que dans le mod_rewrite, .htaccess travaille, obtient le chemin absolu du fichier demandé. Pour transférer à la RewriteRule, mod_rewrite coupe le chemin vers le .htaccess. Puis RewriteRule règles une par une demande de changement de séquence. Et après que la demande est modifiée, Apache doit rétablir le chemin absolu vers le fichier qu'il devrait éventuellement être traitée. RewriteBase fait un hack qui permet de restaurer le chemin d'origine du fichier.

RewriteBase effectuée après toutes les transformations. Cela signifie qu'il ne changera pas entre la RewriteRule de requête, et entrera en vigueur que lorsque tous les RewriteRule fonctionnera.

Après tous les changements RewriteBase regarde par rapport tourné à la fin ou un chemin absolu. Dans le contexte Apache, il fait référence à un chemin relatif ou absolu, en comptant à partir de la racine du site:

  • images / logo.gif - relative.
  • /images/logo.gif - absolue (commençant slash).
  • http://example.com/images/logo.gif - le plus absolu de tous.

Si le chemin est absolu, RewriteBase ne fait rien. Et si un parent - RewriteBase se joint à la gauche. Cela fonctionne aussi bien pour les redirections internes et externes:

# .htaccess находится в /images/
# RewriteBase указан /images/
RewriteBase /images/

# Запрос http://example.com/images/logo.gif
# На вход RewriteRule попадает "logo.gif"
RewriteRule ^logo.gif$ logo-orange.gif
# После RewriteRule: "logo.gif" -> "logo-orange.gif"
# После RewriteBase: "logo-orange.gif" -> "/images/logo-orange.gif"

# Запрос http://example.com/images/header.png
# На вход RewriteRule попадает "header.png"
RewriteRule ^header.png$ /templates/rebranding/header.png
# После RewriteRule: "header.png" -> "/templates/rebranding/header.png"
# После RewriteBase: ничего не меняется, так итоговый результат преобразований начинается со "/'.

# Запрос http://example.com/images/director.tiff
# На вход RewriteRule попадает "director.tiff"
# Используем внешний относительный редирект
RewriteRule ^director.tiff$ staff/manager/director.tiff [R=301]
# После RewriteRule: "director.tiff" -> "staff/manager/director.tiff"
# + mod_rewrite запомнил, что будет внешний редирект
# После RewriteBase: "staff/manager/director.tiff" -> "/images/staff/manager/director.tiff"
# mod_rewrite вспомнил про внешний редирект:
# "/images/staff/manager/director.tiff" -> http://example.com/images/staff/manager/director.tiff

Habituellement, après une certaine familiarité avec mod_rewrite développe la prochaine habitude: 1) dans tous les .htaccess ajouter «RewriteBase /», 2) commencent tous par une redirection de slash: «RewriteRule news.php /index.php?act=news». Cela aide à se débarrasser des artefacts travaillent RewriteBase, mais le font de manière incorrecte. Maintenant que nous savons ce qui rend le RewriteBase, peut être formulé en suivant les règles correctes:

  1. RewriteBase doit correspondre au chemin de la racine du site en .htaccess.
  2. Racine redirection vers "/" vous devez uniquement lorsque vous devez spécifier un chemin absolu de la racine du site dans le fichier.
Как на самом деле работает mod_rewrite. Пособие для продолжающих

Qu'est-ce qui se passe si vous ne spécifiez pas RewriteBase? Par défaut, Apache rend égal au chemin absolu du système de fichiers .htaccess (par exemple, /var/www/example.com/templates/). L'inexactitude de cette hypothèse Apache montré sur les redirections externes relatifs:

# Запрос http://example.com/index.php
# DocumentRoot: /var/www/example.com/
# .htaccess находится в корне сайта, и в нем НЕ УКАЗАН RewriteBase.
# Поэтому по умолчанию RewriteBase равен абсолютному пути до .htaccess: /var/www/example.com/

# На входе RewriteRule - "index.php"
RewriteRule ^index.php main.php [R]
# На выходе: "index.php" -> "main.php"
# mod_rewrite запомнил, что нужен внешний редирект

# Закончились RewriteRule
# mod_rewrite все равно выполняет RewriteBase, так как у него есть значение по умолчанию.
# Получается: "main.php" -> "/var/www/example.com/main.php"

# Здесь mod_rewrite вспоминает, что был внешний редирект:
# "/var/www/example.com/main.php" -> http://example.com/var/www/example.com/main.php

# Получилось совсем не то, что имели в виду.

Ainsi, une demande est passée par tous les RewriteRule, puis à lui, si nécessaire, a ajouté RewriteBase. Si maintenant Apache pour donner le fichier qui montre le chemin qui en résulte? Non. Maintenant , la demande résultant sera traitée à nouveau.

Comment mod_rewrite. Le drapeau [L]

mod_rewrite commence à traiter encore et encore la demande, tant qu'il ne cesse de changer. Et le drapeau [L] ne peut pas l'arrêter.

Dans l' élaboration d'une configuration mod_rewrite plus ou moins complexe est important de comprendre que la demande de changement ne se termine pas le dernier RewriteRule. Une fois travaillé dernière RewriteRule règle et a été ajouté RewriteBase, mod_rewrite regards, demande de modification ou non. Si la demande est modifiée, son traitement recommence depuis le début de .htaccess.

Apache le fait, car il pourrait être transféré vers un autre répertoire dans la demande de modification. Il peut avoir son propre .htaccess, qui n'a pas été impliqué dans le traitement de la requête précédente. La même chose peut être de nouvelles règles .htaccess qui influent sur le traitement des requêtes - mod_rewrite règles et règlements, comme d'autres modules. Pour gérer correctement cette situation, Apache devrait fonctionner à nouveau le cycle de traitement complet.

- Attendez une minute, mais il y a un drapeau [L], qui arrête le traitement de la demande mod_rewrite'om!

Pas exactement. Le drapeau [L] arrête l'itération courante de la requête. Toutefois, si la demande a été modifiée par RewriteRule, qui avait encore à travailler, Apache cycle de traitement de la demande va commencer à nouveau avec le premier RewriteRule.

# Запрос: http://example.com/a.html

RewriteBase /

RewriteRule ^a.html$ b.html [L]
RewriteRule ^b.html$ a.html [L]

L'exemple ci-dessus se traduira par une boucle infinie de redirections et «Internal Server Error» à la fin. Dans cet exemple, une boucle infinie est évidente, mais dans d'autres configurations complexes peut nécessiter de creuser dans les règles pour déterminer quelles requêtes en boucle ensemble.

Pour éviter de telles situations, il est recommandé d'utiliser le drapeau [L] seulement si nécessaire. Le besoin peut être de deux types:

  1. Lorsque vous utilisez une redirection externe - [L, R = 301] ou [L, R = 302]. Dans le cas d'une demande de redirection externe traitement ultérieur est indésirable (voir. Ci-dessous au sujet du drapeau [R]), et il est préférable d'arrêter
  2. Quand il .htaccess boucle, à partir de laquelle aucune échappatoire, et mod_rewrite'om traitement des requêtes devrait être forcé d'arrêter. Dans ce cas, la conception spéciale - voir plus loin dans l'article des conseils sur le sujet ..

Mais l'exemple suivant ne sera pas se coincer. Essayez de déterminer pourquoi, et ce que le fichier résultat sera donné Apache'm.

# Запрос: http://example.com/a.html
# Начало .htaccess

RewriteBase /
RewriteRule ^a.html$ b.html
RewriteRule ^b.html$ a.html

# Конец .htaccess

Comment mod_rewrite. Flag [R]

Flag [R] ne cesse de traiter la demande, retourner immédiatement redirection externe. Au lieu de cela, il se souvient de la nécessité d'une redirection externe, et le traitement des requêtes continue suivante RewriteRule. Il est recommandé de toujours utiliser le drapeau [L].

Flag [R] indique à Apache, vous ne devez pas effectuer de redirection interne et externe. Ce qui est différent de la redirection externe interne? redirection interne modifie simplement le chemin vers le fichier, qui sera remis à l'utilisateur, et l'utilisateur constate que reçoit le fichier, qu'il avait initialement demandé. Dans le même externe redirection Apache retourne à l'utilisateur de l'état de la réponse au lieu du contenu du fichier 301 ou 302 et signalé un lien pour le navigateur doit contacter pour récupérer un fichier.

Il semble que lorsque le traitement du drapeau [R] Apache doit immédiatement arrêter le traitement RewriteRule et retourner à l'utilisateur de la redirection externe. Cependant, rappelons-nous un exemple fantastique de la section «Comment fait RewriteRule». Dans ce document, nous avons identifié d'abord le drapeau [R], indiquant la nécessité d'une redirection externe, puis sommes allés à changer le lien suivant RewriteRule.

Voilà comment Apache fonctionne en spécifiant une redirection externe. Il a simplement «marques» à moi-même que, après toutes les règles que vous avez besoin de retourner le statut de 302 (par défaut), mais il continue d'exécuter tous les RewriteRule plus bas dans la liste. Nous pouvons continuer à modifier la requête que nous avons besoin, la seule chose qui ne fonctionne pas - faire une redirection de retour dans les terres.

Cependant, il est peu probable que vous aurez envie de revenir après la redirection externe un moyen de le changer. Par conséquent, il est recommandé dans l'utilisation du drapeau [R] pour spécifier en conjonction avec le [L]:

# BlackJack переехал на красивое имя
RewriteRule ^bj/(.*) blackjack/$1 [R=301,L]

# Можно использовать просто внешнюю ссылку
RewriteRule ^bj/(.*) http://blackjack.example.com/$1 [L]

Au lieu d'utiliser un drapeau [R], vous pouvez spécifier simplement un lien externe. Dans ce cas, Apache lui-même deviner que vous devez faire des redirections externes. Ici, comme dans le cas d'une indication claire du drapeau [R], nous vous recommandons d'utiliser un drapeau [L].

  • Si la redirection externe conduit au même site, il est préférable d'utiliser un drapeau [R] sans spécifier un lien complet (en d'autres termes, utiliser un rapport de redirection externe). Cela rendra la règle indépendante du nom du site.
  • Si elle est une redirection externe vers un autre site, ou en indiquant un lien externe complet, il ne fonctionne pas.

Comment mod_rewrite. Notez les paramètres de la requête et le drapeau [QSA]

Modification des paramètres de la requête dans le RewriteRule ne change pas la ligne qui passe à côté RewriteRule. Toutefois, lorsque vous modifiez les paramètres de la variable changements% {QUERY_STRING}, qui peut fonctionner RewriteCond.

Terminologie: «paramètres» - les paramètres de la requête, "arguments" - les arguments RewriteRule.

Avec RewriteRule peut changer non seulement le chemin d'accès au fichier à traiter, mais les paramètres de la requête GET à transmettre à lui. Il est souvent utilisé pour le traitement de la transmission dans le script général de gestionnaire CNC, par exemple:

RewriteBase /

# Запрос: http://example.com/news/2010/07/12/grand-opening.html
# На входе: "news/2010/07/12/grand-opening.html"
RewriteRule ^news/(.*)$ index.php?act=news&what=$1
# После RewriteRule: "news/2010/07/12/grand-opening.html" -> "index.php"
# %{QUERY_STRING}: "" -> "act=news&what=2010/07/12/grand-opening.html"

À une époque où la RewriteRule règle rencontre un point d'interrogation dans le second argument, il se rend compte qu'il ya un changement de paramètres de la requête. En conséquence, ce qui suit se produit:

  1. RewriteRule remplace la chaîne avec laquelle il travaille sur la partie du deuxième argument du point d' interrogation. Notez que les nouveaux paramètres de la requête ne tombent pas dans la ligne, qui se déroulera les prochaines règles RewriteRule.
  2. Une partie du second argument , après le point d' interrogation arrive à la variable% {QUERY_STRING}. Si le drapeau a été spécifié [QSA], les paramètres de la requête à ajouter à la partie supérieure de% {QUERY_STRING}. Si le drapeau est pas spécifié,% {QUERY_STRING} remplacer complètement les paramètres de la RewriteRule de requête.

Quelques exemples:

RewriteBase /

# Запрос: http://example.com/news/2010/?page=2
# На входе RewriteRule: "news/2010/"
RewriteRule ^news/(.*)$ index.php?act=news&what=$1
# После преобразования: "news/2010/" -> "index.php"
# Значение %{QUERY_STRING}: "page=2" -> "act=news&what=2010/"

Très probablement, la règle ci-dessus ne fonctionne pas correctement, parce que l'argument est perdu page. Fix it:

RewriteBase /

# Запрос: http://example.com/news/2010/?page=2
# На входе RewriteRule: "news/2010/"
RewriteRule ^news/(.*)$ index.php?act=news&what=$1 [QSA]
# После преобразования: "news/2010/" -> "index.php"
# Значение %{QUERY_STRING}: "page=2" -> "act=news&what=2010/&page=2"

Nous avons ajouté que le drapeau [QSA], et généralement commencé à travailler correctement.

azhno comprendre que le changement des paramètres de requête changent% {QUERY_STRING}, qui peut être utilisé plus tard dans la RewriteCond. Ceci doit être pris en compte lors de l'élaboration des règles suivantes qui vérifient le cas.

- Bien sûr, cela varie, car une demande va retraiter Apache'm!

Non,% {QUERY_STRING} change immédiatement. La preuve ne se traduira pas - sur les paramètres déjà écrit plus intéressant à lire :)

Que pouvez-vous faire pour vérifier dans RewriteCond exactement les paramètres de la requête que l'utilisateur a passé, mais pas modifié RewriteRule'ami? Voir les astuces à la fin.

RewriteCond et la performance

S'il vous plaît vérifier si la demande avec RewriteRule, puis - conditions supplémentaires RewriteCond.

Quelques mots doivent être dit à propos de l'ordre dans lequel mod_rewrite effectue la directive. Depuis RewriteCond .htaccess aller d'abord, puis le RewriteRule, il semble que mod_rewrite vérifie d'abord toutes les conditions, et ensuite procéder à la mise en œuvre RewriteRule.

En fait, tout est à l'opposé. Tout d'abord, les contrôles mod_rewrite si la valeur actuelle de la requête correspond à l'expression régulière de la RewriteRule, et alors seulement vérifier toutes les conditions énumérées dans le RewriteCond.

Donc, si vous avez un regex RewriteRule sur deux pages et vous pensez à la performance, nous avons décidé de limiter l'application de cette règle, RewriteCond supplémentaire, vous savez - il ne fonctionnera pas. Dans ce cas , il est préférable d'utiliser les drapeaux RewriteRule [C] ou [S], pour laisser la règle plus compliquée, si un simple test n'a pas fonctionné.

Les variables et les drapeaux RewriteCond, RewriteRule autres drapeaux, etc.

Lisez la documentation.

Nous avons rencontré les principes de la RewriteRule, RewriteBase, drapeau [L], [R] et [QSA], ainsi que le moteur de recherche démonté l'intérieur mod_rewrite. De gauche inchangée: d'autres drapeaux RewriteRule, directives RewriteCond et RewriteMap.

Heureusement, ces directives et les drapeaux ne sont pas lourd de tous les casse-tête et fonctionnent exactement comme décrit dans la plupart des manuels. Pour les comprendre, il suffit de vérifier la documentation officielle. Tout d'abord, je recommande d'étudier la liste des variables qui peuvent être vérifiés dans le RewriteCond -% {QUERY_STING},% {THE_REQUEST},% {REMOTE_ADDR},% {HTTP_HOST},% {HTTP: header}, etc.) ..

La différence dans le contexte mod_rewrite .htaccess et dans le contexte de l'hôte virtuel

Dans le contexte de mod_rewrite fonctionne exactement le contraire.

Comme je l'ai dit au début, tout ce qui précède concerne l'utilisation mod_rewrite dans le contexte .htaccess. Si mod_rewrite est utilisé Il fonctionnera d'une manière différente:

  • la en RewriteRule il obtient tout le chemin à la demande, de la première barre oblique pour commencer des paramètres GET: «http://example.com/some/news/category/post.html?comments_page=3» -> "/ nouvelles / catégorie / poste. html ". Cette ligne commence toujours avec /.
  • Le deuxième argument de RewriteRule est également nécessaire de commencer avec /, sinon il sera «Bad Request».
  • RewriteBase n'a pas de sens.
  • droit de passage a lieu une seule fois. Le drapeau [L] se termine vraiment le traitement de toutes les règles décrites dans Sans itérations ultérieures.

Astuces et solutions

Il contient des conseils qui peuvent être cités dans le cadre de l'article, mais ont été exclus du texte principal par souci de brièveté de la matière.

Préparation des expressions régulières

Essayez d'être des expressions régulières de sorte qu'ils sont plus étroitement définis précisément les requêtes que vous souhaitez modifier - pour statuer accident de RewriteRule n'a pas fonctionné pour une autre requête. Par exemple:

# Начинайте все регулярные выражения с "^" (признак начала строки)
# и заканчивайте "$" (признак конца строки):
RewriteRule ^news.php$ index.php
# Даже если в этом нет необходимости - для универсальности и лучшего понимания конфигурации:
RewriteRule ^news/(.*)$ index.php

# Если под маску должны попадать только цифры - укажите это явно.
# Если какие-то цифры постоянны, укажите их явно.
# Если в оставшейся части запроса не могут присутствовать слеши, ограничьте их присутствие.
# Не забывайте экранировать "." (точки).
# Следующее правило нацелено на запросы вида http://example.com/news/2009/07/28/b-effect.html
RewriteRule ^news/20[0-9]{2}/[0-9]{2}/[0-9]{2}/[^/]+\.html index.php

Cependant, les expressions régulières, et vous pouvez lire sur notre site:

Les changements dans les redirections externes

Malgré le fait que même vous permet de modifier les mod_rewrite redirections externes, jusqu'à le protocole, je recommande fortement de ne pas utiliser RewriteRule pour ce faire. Dans cet article, un exemple d'un changement dans les redirections externes uniquement utilisés pour se débarrasser des concepts tels que les «liens» et «fichiers» et montrer plus clairement que le RewriteRule fonctionne avec une simple chaîne de caractères.

Je ne pense pas que les développeurs Mod_rewrite supposé que quelqu'un ferait cela, donc il peut y avoir toutes sortes d'objets. Ne pas faire cela, s'il vous plaît.

Comment arrêter une boucle infinie

Parfois, la logique de redirection sur le site Web est que sans mod_rewrite d'action spécial les considère comme une boucle infinie de redirections. Prenons l'exemple suivant.

Le site était une page /info.html. un spécialiste du référencement a décidé que les moteurs de recherche indexent cette page meilleure, si elle sera appelée et demandé de faire redirection externe /information.html à info.html sur information.html. Cependant, pour certaines raisons, leur développeur de site ne peut pas simplement renommer info.html en information.html et de faire une redirection - il a besoin pour être sûr que les données ont été données directement à partir du fichier info.html. Il écrit la règle suivante:

# сделать внешний редирект
RewriteRule ^info.html information.html [R,L]
# но по запросу /information.html все равно отдать info.html
RewriteRule ^information.html info.html

... Et face à une boucle infinie. Chaque /information.html demande reçoit une redirection externe vers /information.html.

La solution est d'au moins deux façons. Habré a déjà été décrit l'un d'entre eux - vous devez définir une variable d'environnement et basé sur sa valeur pour arrêter la redirection. Le code ressemblera à ceci:

RewriteCond %{ENV:REDIRECT_FINISH} !^$
RewriteRule ^ - [L]

RewriteRule ^info.html$ information.html [R,L]
RewriteRule ^information.html$ info.html [E=FINISH:1]

S'il vous plaît noter que le nom de la variable ajoute 'REDIRECT_' mod_rewrite.

La deuxième façon - pour vérifier dans THE_REQUEST, qu'il a été demandé par l'utilisateur:

# Внешний редирект происходит только если пользователь запросил info.html.
# Если же info.html - это результат внутреннего перенаправления, правило срабатывать не будет.
RewriteCond %{THE_REQUEST} "^(GET|POST|HEAD) /info.html HTTP/[0-9.]+$"
RewriteRule ^info.html$ information.html [R,L]

RewriteRule ^information.html$ info.html

L'analyse de la requête de l'utilisateur d'origine - la lutte contre la divulgation d'Apache Liens

Lors du traitement d'une requête Apache ouvre codés caractères (URL-codée) à partir de la demande initiale. Dans certains cas, cela peut ne pas être souhaitable - le développeur veut vérifier est la demande de l'utilisateur original, non modifié. Vous pouvez le faire en vérifiant la variable dans la RewriteCond% {THE_REQUEST}:

RewriteCond %{THE_REQUEST} ^GET[\ ]+/tag/([^/]+)/[\ ]+HTTP.*$
RewriteRule ^(.*)$ index.php?tag=%1 [L]

documents recommandés

La documentation officielle d'Apache

détails techniques