Pouah, ce comportement est tellement irritant. Il n'apparaît même pas à être documentées.
Note: j'ai creusé profondément dans cette (pouah) après mon post original, donc, cela a été fortement modifié.
.htaccess par-dir contexte
Voici ce qui semble arriver en .htaccess
% - répertoire (par dir) contexte:
Supposons qu'un processus Apache .htaccess
fichier qui contient les réécrire les directives.
-
Apache remplit sa variable d'environnement carte avec tous de la norme CGI / Apache variables
-
La réécriture commence
-
Variables d'environnement sont définies en RewriteRule
directives
-
Quand Apache arrête le traitement de la RewriteRule
directives (à cause d'un L
drapeau ou à la fin de la base de règles) et l'URL a été modifiée par un RewriteRule
, Apache redémarre le traitement de la demande.
Si vous n'êtes pas familier avec cette partie, voir l' L
drapeau de la documentation:
ainsi, la base de règles peut être exécutée à nouveau depuis le début. Le plus souvent ce qui va vous arriver si l'une des règles provoque une redirection interne ou externe - origine du processus de demande de recommencer.
-
De ce que je peux observer, je crois que quand #4 qui se passe, #1 est répété, alors les variables d'environnement qui ont été mis en RewriteRule
directives sont précédées de "REDIRECT_" et ajouté les variables d'environnement de la carte (pas nécessairement dans cet ordre, mais le résultat final composé de la combinaison).
Cette étape est où le choisi les noms de variables sont effacées, et dans un instant je vais vous expliquer pourquoi c'est si important et gênant.
La restauration des noms de variables
Quand je suis tombé sur cette question, je faisais quelque chose comme ce qui suit dans .htaccess
(simplifié):
RewriteCond %{HTTP_HOST} (.+)\.projects\.
RewriteRule (.*) subdomains/%1/docroot/$1
RewriteRule (.+/docroot)/ - [L,E=EFFECTIVE_DOCUMENT_ROOT:$1]
Si je devais définir la variable d'environnement dans le premier RewriteRule
, Apache doit reprendre le processus de réécriture et ajouter la variable "REDIRECT_" (mesures n ° 4 et 5 ci-dessus), donc je voudrais perdre l'accès à travers le nom que j'ai attribué.
Dans ce cas, la première RewriteRule
modifie l'URL, donc après les deux RewriteRule
s sont traitées, Apache redémarrage de la procédure et des processus de l' .htaccess
de nouveau. La deuxième fois, la première RewriteRule
est ignorée en raison de l' RewriteCond
directive, mais le second, RewriteRule
correspond à, définit la variable d'environnement (de nouveau), et, surtout, de ne pas modifier l'URL. Si la demande / le processus de réécriture ne pas recommencer, et le nom de la variable, j'ai choisi de bâtons. Dans ce cas, j'ai effectivement les deux REDIRECT_EFFECTIVE_DOCUMENT_ROOT
et EFFECTIVE_DOCUMENT_ROOT
. Si je devais utiliser un L
drapeau sur la première RewriteRule
, j'avais seulement EFFECTIVE_DOCUMENT_ROOT
.
@truelle partielle de la solution fonctionne de la même façon: la réécriture directives sont traitées à nouveau, le nouveau nom de la variable est attribuée à l'origine le nom de nouveau, et si l'URL ne change pas, le processus est terminé, et le affectée nom de la variable de bâtons.
Pourquoi ces techniques sont insuffisantes
Deux de ces techniques souffrent d'un défaut majeur: lorsque les règles de réécriture dans l' .htaccess
le fichier où vous définissez les variables d'environnement de réécrire l'URL d'un plus profondément imbriqués répertoire qui a un .htaccess
le fichier qui permet une réécriture, votre nom de variable est effacé de nouveau.
Disons que vous avez un annuaire de mise en page comme ceci:
docroot/
.htaccess
A.php
B.php
sub/
.htaccess
A.php
B.php
Et un docroot/.htaccess
comme ceci:
RewriteRule ^A\.php sub/B.php [L]
RewriteRule .* - [E=MAJOR:flaw]
Si vous demandez /A.php
, et c'est réécrite sub/B.php
. Vous avez encore votre MAJOR
variable.
Toutefois, si vous avez des réécrire les directives en docroot/sub/.htaccess
(même RewriteEngine Off
ou RewriteEngine On
), votre MAJOR
variable disparaît. C'est parce qu'une fois que l'URL est réécrite sub/B.php
, docroot/sub/.htaccess
est traitée, et si elle contient tout réécrire les directives, la réécriture de directives en docroot/.htaccess
ne sont pas traités à nouveau. Si vous aviez un REDIRECT_MAJOR
après docroot/.htaccess
a été traité (par exemple, si vous omettez l' L
drapeau de la première RewriteRule
), vous aurez toujours de l'avoir, mais ces directives ne fonctionne pas à nouveau la valeur de votre choix de nom de variable.
L'héritage
Donc, disons que vous voulez:
-
définir des variables d'environnement en RewriteRule
directives à un niveau de l'arborescence du répertoire (comme docroot/.htaccess
)
-
elles seront disponibles dans les scripts à des niveaux plus profonds
-
les mettre à disposition à l'attribution des noms de domaine
-
être en mesure d'avoir de réécriture des directives, en plus profondément imbriqués .htaccess
fichiers
Une solution possible est d'utiliser RewriteOptions inherit
directives dans le plus profondément imbriqués .htaccess
fichiers. Qui vous permet de re-exécuter la réécriture des directives en moins profondément imbriqués les fichiers et utiliser les techniques décrites ci-dessus pour définir les variables avec les noms choisis. Toutefois, notez que cela augmente la complexité, car vous devez être plus prudent de l'élaboration de la réécriture des directives dans le moins profondément imbriqués les fichiers de sorte qu'ils ne causent pas de problèmes lors de l'exécution à nouveau à partir de la plus profondément répertoires imbriqués. Je crois Apache bandes de la per-dir préfixe pour le plus profondément imbriqués répertoire et exécute la réécriture de directives dans le moins profondément imbriqués les fichiers sur cette valeur.
@truelle de la technique de
Aussi loin que je peux voir, le soutien pour l'utilisation d'une construction comme %{ENV:REDIRECT_VAR}
de la valeur de la composante d'un RewriteRule
E
indicateur (par exemple, [E=VAR:%{ENV:REDIRECT_VAR}]
) ne semble pas être documentés:
VAL peut contenir des références arrières ($N ou %N) qui seront développées.
Il ne semble pas fonctionner, mais si vous voulez éviter de compter sur quelque chose de sans-papiers (corrigez-moi si je me trompe à ce sujet), il peut facilement être fait de cette façon:
RewriteCond %{ENV:REDIRECT_VAR} (.+)
RewriteRule .* - [E=VAR:%1]
SetEnvIf
Je ne recommande pas se fier sur ce point, car il ne semble pas être compatible avec le comportement documenté (voir ci-dessous), mais ce (en docroot/.htaccess
, avec Apache 2.2.20) fonctionne pour moi:
SetEnvIf REDIRECT_VAR (.+) VAR=$1
Seules les variables d'environnement définies par SetEnvIf[NoCase] précédentes directives sont disponibles pour le test de cette manière.
Pourquoi?
Je ne sais pas ce que la justification de la préfixation de ces noms avec "REDIRECT_" est -- pas surprenant, car il ne semble pas être mentionné dans la documentation d'Apache sections pour les directives de mod_rewrite, RewriteRule
drapeaux, ou des variables d'environnement.
Au moment où il semble comme une nuisance importante pour moi, en l'absence d'une explication de pourquoi c'est mieux que de laisser l'attribution des noms de domaine seul. Le manque de documentation contribue à mon scepticisme à ce sujet.
Être capable de définir des variables d'environnement dans les règles de réécriture est utile, ou au moins, il serait. Mais l'utilité est fortement diminuée par ce nom de changement de comportement. La complexité de ce post illustre comment les noix de ce comportement et les cerceaux qui doivent être sauté à travers d'essayer de le surmonter.