74 votes

Lors de la définition des variables d'environnement d'Apache directives RewriteRule, quelles sont les causes de la variable nom de préfixe "REDIRECT_"?

Je suis en train de mettre Apache variables d'environnement (pour une utilisation en PHP) avec l' [E=VAR:VAL] drapeau sur des règles de réécriture des règles .fichier htaccess.

J'ai déjà découvert les variables sont accessibles en PHP les variables de serveur $_SERVER plutôt que d' $_ENV (ce qui rend d'une certaine quantité de sens). Cependant, mon problème est que certaines règles de l' [E=VAR:VAL] indicateur fonctionne comme prévu et je me retrouve avec une variable $_SERVER['VAR'] , mais pour les autres règles, je termine avec une variable $_SERVER['REDIRECT_VAR'] ou $_SERVER['REDIRECT_REDIRECT_VAR'], etc

A. Quelles sont les causes d'une variable d'environnement d'Apache à l'aide de l' [E=VAR:VAL] drapeau pour obtenir renommé "REDIRECT_" préfixer le nom de la variable?

B. Que puis-je faire pour m'assurer que je me retrouve avec une Variable d'Environnement avec un même nom afin que je puisse y accéder en PHP $_SERVER['VAR'] sans avoir à recourir à la vérification des variations de la variable nom en avoir un de plus les instances de "REDIRECT_" ajouté à cela?

Solution partielle trouvée. Adjonction de ce qui suit le début de la réécriture des règles recrée l'original ENV:VAR sur chaque redirection (ainsi que de quitter le REDIRECT_VAR versions) si on a besoin de:

RewriteCond %{ENV:REDIRECT_VAR} !^$
RewriteRule .* - [E=VAR:%{ENV:REDIRECT_VAR}]

76voto

JMM Points 4032

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.

  1. Apache remplit sa variable d'environnement carte avec tous de la norme CGI / Apache variables

  2. La réécriture commence

  3. Variables d'environnement sont définies en RewriteRuledirectives

  4. 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.
  5. 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 RewriteRules 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:

  1. définir des variables d'environnement en RewriteRule directives à un niveau de l'arborescence du répertoire (comme docroot/.htaccess)

  2. elles seront disponibles dans les scripts à des niveaux plus profonds

  3. les mettre à disposition à l'attribution des noms de domaine

  4. être en mesure d'avoir de réécriture des directives, en plus profondément imbriqués .htaccessfichiers

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.

9voto

thetaiko Points 5620

Je n'ai pas testé ce à tous et je sais qu'il ne faut pas aborder les points A ou B, mais il y a une description de cette question dans les commentaires de documentation de PHP et des solutions possibles pour accéder à ces variables à l'aide d' $_SERVER['VAR']:

http://www.php.net/manual/en/reserved.variables.php#79811

EDIT - certains plus de réponses à la question offertes:

Un: Les variables d'environnement sont renommés par Apache s'ils sont impliqués dans une redirection. Par exemple, si vous avez la règle suivante:

RewriteRule ^index.php - [E=VAR1:'hello',E=VAR2:'world']

Ensuite, vous pouvez accéder à VAR1 et VAR2 l'aide d' $_SERVER['VAR1'] et $_SERVER['VAR2']. Toutefois, si vous rediriger la page comme ceci:

RewriteRule ^index.php index2.php [E=VAR1:'hello',E=VAR2:'world']

Ensuite, vous devez utiliser $_SERVER['REDIRECT_VAR1'], etc.

B: La meilleure façon de surmonter ce problème est de traiter les variables qui vous intéressent à l'aide de PHP. Créer une fonction qui s'exécute par le biais de l' $_SERVER tableau et trouve les objets dont vous avez besoin. Vous pouvez même utiliser une fonction comme ceci:

function myGetEnv($key) {
    $prefix = "REDIRECT_";
    if(array_key_exists($key, $_SERVER))
        return $_SERVER[$key];
    foreach($_SERVER as $k=>$v) {
        if(substr($k, 0, strlen($prefix)) == $prefix) {
            if(substr($k, -(strlen($key))) == $key)
                return $v;
        }
    }
    return null;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X