在Apache RewriteRule指令中设置环境变量时,什么导致变量名称以“REDIRECT_”为前缀? [英] When setting environment variables in Apache RewriteRule directives, what causes the variable name to be prefixed with "REDIRECT_"?

查看:148
本文介绍了在Apache RewriteRule指令中设置环境变量时,什么导致变量名称以“REDIRECT_”为前缀?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在.htaccess文件中的RewriteRule规则上设置Apache环境变量(用于PHP)与 [E = VAR:VAL] 标志。 / p>

我已经发现,变量在PHP中被访问作为服务器变量 $ _ SERVER 而不是 $ _ENV (这有一定的意义)。然而,我的问题是一些规则, [E = VAR:VAL] 标志的工作原理和我最终得到一个变量 $ _ SERVER [' VAR'] 但对于其他规则,我以变量 $ _ SERVER ['REDIRECT_VAR'] $ _ SERVER [ REDIRECT_REDIRECT_VAR'] 等等



A。使用 [E = VAR:VAL] 标记在Apache中设置的环境变量是通过将REDIRECT_添加到变量名中来重命名的呢?



B。我可以做些什么来确保我使用一个不变名称的环境变量,以便我可以在PHP中以 $ _ SERVER ['VAR'] 检查具有REDIRECT_的其中一个实例的变量名称的变体。



部分解决方案。将以下内容添加到重写规则的开始时,如果需要,可以在每个重定向上重新创建原始ENV:VAR(以及将REDIRECT_VAR版本保留):

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


解决方案

这种行为是不幸的,甚至没有被证明。



.htaccess per-dir context



以下是 .htaccess -directory(per-dir)context:



假设Apache处理包含重写指令的 .htaccess 文件。



$ ol




  • Apache将其环境变量映射到所有标准CGI / Apache变量








  • 重写开始








  • Environme $ t


    $ b $ >


    当Apache停止处理 RewriteRule 指令(因为 L 标志或规则集的结尾),URL由 RewriteRule 更改,Apache重新启动请求处理。




    如果您对本部分不熟悉,请参阅 L 标志文档


    ,因此规则集可能会从头开始再次运行。最常见的情况是,如果其中一个规则导致重定向(内部或外部)导致请求过程重新启动,则会发生这种情况。








  • 从我可以观察,我相信当#4发生时,#1被重复,然后在 RewriteRule 指令中设置的环境变量前面加上 REDIRECT _ 并添加到环境vars映射(不一定按照该顺序,但最终结果由该组合组成)。




    这一步是删除所选变量名的地方,稍后我将解释为什么这么重要和不方便。







  • 恢复变量名称



    当我最初遇到这个问题时,我在 .htaccess (简化)中做了类似以下操作:

      RewriteCond%{HTTP_HOST}(。+)\.projects\。 

    RewriteRule(。*)子域/%1 / docroot / $ 1

    RewriteRule(。+ / docroot)/ - [L,E = EFFECTIVE_DOCUMENT_ROOT:$ 1]

    如果我要在第一个 RewriteRule Apache将重新启动重写过程,并使用 REDIRECT _ (上述步骤#4和5)添加变量,因此我将无法通过我分配的名称访问该变量



    在这种情况下,第一个 RewriteRule 更改了URL,因此在 RewriteRule 被处理,Apache重新启动该过程并再次处理 .htaccess 。第二次,由于 RewriteCond 指令,第一个 RewriteRule 被跳过,而第二个 RewriteRule 匹配,设置环境变量(再次),重要的是,不会更改URL 。所以请求/重写过程不会重新开始,而我选择的变量名称是stick。在这种情况下,我实际上同时具有 REDIRECT_EFFECTIVE_DOCUMENT_ROOT EFFECTIVE_DOCUMENT_ROOT 。如果我在第一个 RewriteRule 上使用 L 标志,我只会有 EFFECTIVE_DOCUMENT_ROOT



    @ trowel的部分解决方案的工作方式类似:重写指令被再次处理,重命名的变量再次分配给原始名称,如果URL没有改变,则该过程已经结束,并且所分配的变量名称被粘贴。



    为什么这些技术不足



    这两种技术都有很大的缺陷:当您设置环境变量的 .htaccess 文件中的重写规则将URL重写为更深入嵌套的目录,有一个 .htaccess 文件进行任何重写,您的分配的变量名被再次删除。



    说你有一个这样的目录布局:

      docroot / 
    .htaccess
    A.php
    B .php
    sub /
    .htaccess
    A.php
    B.php

    还有一个 docroot /。 htaccess 如下:

      RewriteRule ^ A \.php sub / B.php [L] 

    RewriteRule。* - [E = MAJOR:缺陷]

    所以你请求 /A.php ,并将其重写为 sub / B.php 。您仍然有 MAJOR 变量。



    但是,如果您在中有任何重写指令, docroot / sub / .htaccess (甚至只是 RewriteEngine Off RewriteEngine On ),你的 MAJOR 变量消失。这是因为一旦将URL重写为 sub / B.php ,则处理 docroot / sub / .htaccess 如果它包含任何重写指令,则不会再次处理 docroot / .htaccess 中的重写指令。如果在 docroot / .htaccess 被处理后,如果您有 REDIRECT_MAJOR (例如,如果省略 L 标志从第一个 RewriteRule ),你仍然可以,但这些指令不会再运行,以设置您选择的变量名称。



    继承



    所以,说你想:






    1. 中设置环境变量RewriteRule 目录树的特定级别(如 docroot / .htaccess








    2. 在更深层次的脚本中可以使用








    3. 可以使用分配的名称








    4. 可以在更深入嵌套的 .htaccess 文件





    解决方案是给我们e RewriteOptions在更深入嵌套的 .htaccess 文件中继承指令。这允许您以较不深入的嵌套文件重新运行重写指令,并使用上述技术来设置所选名称的变量。但是,请注意,这会增加复杂性,因为必须更仔细地在较不深入的嵌套文件中制定重写指令,以便在从更深入的嵌套目录再次运行时不会引起问题。我相信Apache剥去更深入嵌套的目录的每个目录前缀,并在该值不太深的嵌套文件中运行rewrite指令。



    @ trowel的技术



    就我所见,支持在%{ENV:REDIRECT_VAR} 中使用一个构造,一个 RewriteRule E 标志(例如 [E = VAR:%{ENV:REDIRECT_VAR}] )似乎不是记录的


    VAL可能包含将被扩展的反向引用($ N或%N)。


    < blockquote>

    它似乎起作用,但是如果你想避免依赖没有文档的东西(如果我错了,请纠正我),可以很容易地这样做:

      RewriteCond%{ENV:REDIRECT_VAR}(。+)
    RewriteRule。* - [E = VAR: 1]



    SetE nvIf



    我不建议依靠这个,因为它似乎不符合,Apache 2.2.20)适用于我:

      SetEnvIf REDIRECT_VAR(。+)VAR = $ 1 




    只有以前的SetEnvIf [NoCase]指令定义的环境变量才能以这种方式进行测试




    为什么?



    我不知道什么理由将这些名称前缀为 REDIRECT _ 并不奇怪,因为在Apache文档部分中似乎没有提到 mod_rewrite指令 RewriteRule flags ,或环境变量



    目前来看,这似乎是一个很大的麻烦,因为没有解释为什么比离开分配名称。缺乏文档只会对我的怀疑造成怀疑。



    能够在重写规则中分配环境变量是有用的,或至少是有用的。但是,这种名称变化的行为大大减少了实用性。这个帖子的复杂性表明,这种行为和篮球必须跳过来试图克服它是如何。


    I am trying to set Apache environment variables (for use in PHP) with the [E=VAR:VAL] flag on RewriteRule rules in an .htaccess file.

    I have already discovered the variables are accessed in PHP as server variables $_SERVER rather than $_ENV (which makes a certain amount of sense). However, my problem is for some rules the [E=VAR:VAL] flag works as expected and I end up with a variable $_SERVER['VAR'] but for other rules I end with a variable $_SERVER['REDIRECT_VAR'] or $_SERVER['REDIRECT_REDIRECT_VAR'], etc

    A. What causes an environment variable set in Apache using the [E=VAR:VAL] flag to get renamed by having "REDIRECT_" prepended to the variable name?

    B. What can I do to make sure I end up with an Environment Variable with an unchanged name so I can access it in PHP as $_SERVER['VAR'] without having to resort to checking for variations of the variable name having one of more instances of "REDIRECT_" prepended to it?

    Partial solution found. Adding the following to the start of the rewrite rules recreates the original ENV:VAR on each redirect (as well as leaving the REDIRECT_VAR versions there) if they're needed:

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

    解决方案

    This behavior is unfortunate and doesn't even appear to be documented.

    .htaccess per-dir context

    Here's what appears to happen in .htaccess per-directory (per-dir) context:

    Assume that Apache processes an .htaccess file that includes rewrite directives.

    1. Apache populates its environment variable map with all of the standard CGI / Apache variables

    2. Rewriting begins

    3. Environment variables are set in RewriteRule directives

    4. When Apache stops processing the RewriteRule directives (because of an L flag or the end of the ruleset) and the URL has been changed by a RewriteRule, Apache restarts request processing.

      If you're not familiar with this part, see the L flag documentation:

      thus the ruleset may be run again from the start. Most commonly this will happen if one of the rules causes a redirect - either internal or external - causing the request process to start over.

    5. From what I can observe, I believe that when #4 happens, #1 is repeated, then the environment variables that were set in RewriteRule directives are prepended with REDIRECT_ and added to the environment vars map (not necessarily in that order, but the end result consisting of that combination).

      This step is where the chosen variable names are wiped out, and in a moment I will explain why that is so important and inconvenient.

    Restoring variable names

    When I originally ran into this issue, I was doing something like the following in .htaccess (simplified):

    RewriteCond %{HTTP_HOST} (.+)\.projects\.
    
    RewriteRule (.*) subdomains/%1/docroot/$1
    
    RewriteRule (.+/docroot)/ - [L,E=EFFECTIVE_DOCUMENT_ROOT:$1]
    

    If I were to set the environment variable in the first RewriteRule, Apache would restart the rewriting process and prepend the variable with REDIRECT_ (steps #4 & 5 above), thus I'd lose access to it via the name I assigned.

    In this case, the first RewriteRule changes the URL, so after both RewriteRules are processed, Apache restarts the procedure and processes the .htaccess again. The second time, the first RewriteRule is skipped because of the RewriteCond directive, but the second RewriteRule matches, sets the environment variable (again), and, importantly, doesn't change the URL. So the request / rewriting process does not start over, and the variable name I chose sticks. In this case I actually have both REDIRECT_EFFECTIVE_DOCUMENT_ROOT and EFFECTIVE_DOCUMENT_ROOT. If I were to use an L flag on the first RewriteRule, I'd only have EFFECTIVE_DOCUMENT_ROOT.

    @trowel's partial solution works similarly: the rewrite directives are processed again, the renamed variable is assigned to the original name again, and if the URL does not change, the process is over and the assigned variable name sticks.

    Why those techniques are inadequate

    Both of those techniques suffer from a major flaw: when the rewrite rules in the .htaccess file where you set environment variables rewrite the URL to a more deeply nested directory that has an .htaccess file that does any rewriting, your assigned variable name is wiped out again.

    Say you have a directory layout like this:

    docroot/
            .htaccess
            A.php
            B.php
            sub/
                    .htaccess
                    A.php
                    B.php
    

    And a docroot/.htaccess like this:

    RewriteRule ^A\.php sub/B.php [L]
    
    RewriteRule .* - [E=MAJOR:flaw]
    

    So you request /A.php, and it's rewritten to sub/B.php. You still have your MAJOR variable.

    However, if you have any rewrite directives in docroot/sub/.htaccess (even just RewriteEngine Off or RewriteEngine On), your MAJOR variable disappears. That's because once the URL is rewritten to sub/B.php, docroot/sub/.htaccess is processed, and if it contains any rewrite directives, rewrite directives in docroot/.htaccess are not processed again. If you had a REDIRECT_MAJOR after docroot/.htaccess was processed (e.g. if you omit the L flag from the first RewriteRule), you'll still have it, but those directives won't run again to set your chosen variable name.

    Inheritance

    So, say you want to:

    1. set environment variables in RewriteRule directives at a particular level of the directory tree (like docroot/.htaccess)

    2. have them available in scripts at deeper levels

    3. have them available with the assigned names

    4. be able to have rewrite directives in more deeply nested .htaccess files

    A possible solution is to use RewriteOptions inherit directives in the more deeply nested .htaccess files. That allows you to re-run the rewrite directives in less deeply nested files and use the techniques outlined above to set the variables with the chosen names. However, note that this increases complexity because you have to be more careful crafting the rewrite directives in the less deeply nested files so that they don't cause problems when run again from the more deeply nested directories. I believe Apache strips the per-dir prefix for the more deeply nested directory and runs the rewrite directives in the less deeply nested files on that value.

    @trowel's technique

    As far as I can see, support for using a construct like %{ENV:REDIRECT_VAR} in the value component of a RewriteRule E flag (e.g. [E=VAR:%{ENV:REDIRECT_VAR}]) does not appear to be documented:

    VAL may contain backreferences ($N or %N) which will be expanded.

    It does appear to work, but if you want to avoid relying on something undocumented (please correct me if I'm wrong about that), it can easily be done this way instead:

    RewriteCond %{ENV:REDIRECT_VAR} (.+)
    RewriteRule .* - [E=VAR:%1]
    

    SetEnvIf

    I don't recommend relying on this, because it doesn't seem to be consistent with the documented behavior (see below), but this (in docroot/.htaccess, with Apache 2.2.20) works for me:

    SetEnvIf REDIRECT_VAR (.+) VAR=$1
    

    Only those environment variables defined by earlier SetEnvIf[NoCase] directives are available for testing in this manner.

    Why?

    I don't know what the rationale for prefixing these names with REDIRECT_ is -- not surprising, since it doesn't appear to be mentioned in the Apache documentation sections for mod_rewrite directives, RewriteRule flags, or environment variables.

    At the moment it seems like a big nuisance to me, in the absence of an explanation for why it's better than leaving the assigned names alone. The lack of documentation only contributes to my skepticism about it.

    Being able to assign environment variables in rewrite rules is useful, or at least, it would be. But the usefulness is greatly diminished by this name-changing behavior. The complexity of this post illustrates how nuts this behavior and the hoops that have to be jumped through to try to overcome it are.

    这篇关于在Apache RewriteRule指令中设置环境变量时,什么导致变量名称以“REDIRECT_”为前缀?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆