我怎样才能有条件的 .htaccess 块?

Posted

技术标签:

【中文标题】我怎样才能有条件的 .htaccess 块?【英文标题】:How Can I Have A Conditional .htaccess Block? 【发布时间】:2010-10-18 16:51:20 【问题描述】:

这是一个您以前可能遇到过的 Apache 问题。我想要一个可以部署到我的工作站、登台服务器和生产服务器的源程序包,但它可以根据 URL 加载不同的 .htaccess 设置。

请注意,我在调用 IfModule 时使用了 kludge,但这不适用于我们的新生产服务器,因为它与我的登台服务器共享所有相同的模块。

注意,我需要将 SetEnv 与这些重写捆绑在一起。目前如果你使用 RewriteCond,它只与下面的 RewriteRule 相关联,而不是下面的 SetEnv。

【问题讨论】:

【参考方案1】:

这是一个简单的示例,您可以根据自己的要求对其进行更改:

<IfModule mod_rewrite.c>
    RewriteEngine On

    RewriteBase /

    RewriteCond %HTTP_HOST !^localhost
    RewriteCond %HTTP_HOST !^www\.
    RewriteRule (.*) http://www.%HTTP_HOST/$1 [R=301,L]
</IfModule>

【讨论】:

这是否可以连续工作,然后我可以在它下面附加另一个 RewriteCond 并添加更多 RewriteRule 条目,它只适用于以前的 RewriteCond?我的意思是,在普通的编程语言和标记中,你有某种开始/停止块,无论是花括号。但不在这里 还有,RewriteBase / 重要吗? 这种方法的问题是它只适用于RewriteRule,尝试将它也用于SetEnv或php_value,它不起作用。这就是我使用 IfModule 组件的原因。【参考方案2】:

不使用SetEnv,而是使用RewriteRule本身的环境变量设置能力:

RewriteCond %HTTP_HOST =foo.com
RewriteRule ^ - [E=VARNAME:foo]

RewriteCond %HTTP_HOST =bar.com
RewriteRule ^ - [E=VARNAME:bar]

虽然我更喜欢通过在启动时将标志传递给 httpd 进程并使用 IfDefine 块来查找它们来做这种事情。

<IfDefine FOO>
SetEnv VARNAME foo
</IfDefine>

<IfDefine BAR>
SetEnv VARNAME bar
</IfDefine>

【讨论】:

需要注意的是,第一个例子中不能调用Apache中的php_value指令——只能调用环境变量。在第二个示例中,这是最佳选择,因为您可以逐字定义您的服务器。但是,这仅在您控制环境时才有效。如果您在共享主机上,则无法控制将参数传递给 httpd 进程。因此,您可以使用 来寻找它的逆。 我发现我可以使用 IfDefine,因为我的 prod 服务器 100% 由我控制,我可以弄乱 /etc/sysconfig/httpd OPTION 参数并将其设为 OPTIONS="-D prod"。在共享的登台服务器上,我必须使用 IfDefine !prod 然后在它下面堆叠一个 IfModule expires_module。在我的工作站上,我必须使用 IfDefine !prod 和 IfModule !expires_module。这给了我一个 .htaccess 文件,该文件可用于开发、登台/测试和生产。 有点混乱,让我觉得可以在 ifdefine 上使用简单的环境变量 RewriteCond 很难理解。使用定义有点笨拙。我认为更好的解决方案是对 URL 或 IP 地址使用条件。当我弄清楚如何做到这一点时,我将发布作为答案。【参考方案3】:

在 Ubuntu Linux 上IfDefine 的变量在

中设置
/etc/apache2/envvars

并且被称为APACHE_ARGUMENTS。因此,我必须在该文件的底部添加:

export APACHE_ARGUMENTS="-D dev"

...然后弹跳服务器:

/etc/init.d/apache2 stop
/etc/init.d/apache2 start

在其他系统上:

然而,有一篇关于这个主题的 Debian 文章讨论了这个here。在该示例中,要编辑的文件是 /etc/default/apache2,变量名为 APACHE_DEFINES

同样,在某些系统上,它是一个名为 OPTIONS 的变量,设置在 /etc/sysconfig/httpd 中。

所以,您真正需要做的是在您的 apache2ctl 文件中查找开始部分。因此,首先执行whereis apache2ctl 以查找该脚本的位置,将其找出并找到其中包含 apache2 指令的开始部分,并查看它传递的变量是否为 OPTIONSAPACHE_ARGUMENTSAPACHE_DEFINES , 或者是其他东西。然后,通过/etc/sysconfig/httpd/etc/default/apache2/etc/apache2/envvars 的试验,查看您需要编辑的文件。

【讨论】:

【参考方案4】:

我尝试了 IfDefine 方法,但它不起作用,即使我传递给 Apache 启动的定义变量肯定显示在 APACHE_ARGUMENTS 行的 phpinfo() 中。

我尝试了另一种方法,效果很好。在您的 .htaccess 文件中,您需要以下内容:

# Is the domain local (i wanted to check two names)? <If "%SERVER_NAME != 'localhost' && %SERVER_NAME != 'myproject.localhost'"> # I wanted to password protect the production server only AuthType Basic AuthName "Restricted area" AuthUserFile /app/.htpasswd require valid-user </If>

我使用的是 Apache 2.4。可能不适用于早期版本。

【讨论】:

以上是关于我怎样才能有条件的 .htaccess 块?的主要内容,如果未能解决你的问题,请参考以下文章

有条件的,我怎样才能使操作自动化?

Htaccess 规则给出 301 错误

我怎样才能更好地有条件地渲染我的组件?

我有以下测试代码。我怎样才能使这个条件为真

htaccess 删除参数和索引文件

.htaccess 如何为 public_html cpanel 工作