.htaccess在多个环境中的应用

13

我知道类似的问题以前已经被问过,但我没有找到任何特别适合我的情况的答案。

我有一个在多个环境(本地、开发、生产)上运行的ExpressionEngine网站,每个环境都需要不同的.htaccess规则:

所有环境

开发环境

  • 使用.htpasswd密码保护
  • 强制使用HTTPS协议
  • 使用X-Robots-Tag防止搜索引擎索引

生产环境

  • 强制使用HTTPS协议
  • 将非www子域名重定向到www

本地环境

  • 没有特殊规则。
我看到了很多关于如何为每个模块设置特定环境的示例。比如对于mod_rewrite模块,可以使用RewriteCond %{REQUEST_HOST} ^dev.myurl.com,而对于.htpasswd要求,则可以使用类似这样的技巧

但是我真正希望的是能够设置全局环境变量,然后在每个环境中在.htaccess文件中重复使用这些变量。以伪JavaScript作为例子,类似于:

var local = 'mysite.local';
var development = 'dev.mysite.com';
var production = 'www.mysite.com';

// Global .htaccess rules

if(environment == local){
   // Local environment .htaccess rules
}

if(environment == development){
   // Development environment .htaccess rules
}

if(environment == production){
   //Production envirotnment .htaccess rules
}

这样所有特定于环境的规则都被分组在一起,使文件非常干净,如果更改环境,则只需要更改一个变量。
我看到了一些关于修改Apache配置文件中设置的参考资料,但显然,如果我正在处理第三方主机,则这不是可行的选择。
那么这是痴心妄想,还是可以实现的?

我看到了这篇文章,虽然我还没有尝试过,但看起来很有前途。 - kmgdev
2个回答

11

Jon的回答很好。不幸的是,并非所有的网络主机都允许你控制启动 Apache 的 -D 参数。

这里有一种方法可以在开发和生产中使用单个htaccess文件,但只保护开发站点的密码:

# ----------------------------------------------------------------------
# Password protect staging server
# Use one .htaccess file across multiple environments
# (e.g. local, dev, staging, production)
# but only password protect a specific environment.
# ----------------------------------------------------------------------

SetEnvIf Host staging.domain.com passreq
AuthType Basic
AuthName "Password Required"
AuthUserFile /full/path/to/.htpasswd
Require valid-user
Order allow,deny
Allow from all
Deny from env=passreq
Satisfy any

8
这是一种空想的愿望还是可以实现的呢?在我看来,是可以实现的。你永远无法根据环境变量或其他任何东西来获得可预测的规则“范围”。Apache中不存在任意的if(something) { do everything in here }。许多指令在某些范围内不起作用,而且当您需要更改某些内容的工作方式时,您更有可能破坏您已经拥有的内容,而不是简单地修改它。
最好的方法是完全不使用htaccess文件
您应该尽可能避免使用.htaccess文件,如果您有访问httpd主服务器配置文件的权限。使用.htaccess文件会减慢您的Apache http服务器。任何您可以在.htaccess文件中包含的指令都应该在Directory块中设置,因为这样做的效果相同,性能更佳。
为本地、开发和生产创建单独的虚拟主机。根据需要打开或关闭它们,任何全局配置都可以存储在其他位置(例如在名为global.includes的文件中),然后在所有3个虚拟主机中使用Include指令。如果您需要将规则应用于特定目录,请使用<Directory>块而不是htaccess文件。
如果您宁愿将所有内容都放在htaccess文件中,您可以尝试将所有内容放在<IfDefine>块中,这可能是您在问题中的伪代码最接近的东西。基本上是这样的: <IfDefine local> # Your local config here </IfDefine>
<IfDefine dev> # Your dev config here </IfDefine>
<IfDefine prod> # Your production config here </IfDefine>
# Global htaccess rules
RewriteEngine On
RewriteRule ^foo$ /bar [L]

# Only local
<IfDefine LocalInstance>
    RewriteRule ^local/foo /bar [L]
</IfDefine>

# Only dev
<IfDefine DevInstance>
    RewriteRule ^dev/foo /bar [L]
</IfDefine>

# Only production
<IfDefine ProductionInstance>
    RewriteRule ^dev/foo /bar [L]
</IfDefine>

当您启动Apache时,需要通过命令行参数或在vhost配置文件中使用Define指令(只有一个参数)传递-DLocalInstance-DDevInstance-DProductionInstance。虽然看起来很顺畅,但不能保证一切顺利,我之前遇到过<IfDefine>的问题,特别是如果您尝试做得太复杂。


2
在Apache HTTP Server v2.4中,其中一个核心增强功能是:<If>、<ElseIf>和<Else>部分可以根据每个请求的条件设置配置,只要您想使用的内容支持目录上下文。http://httpd.apache.org/docs/trunk/mod/core.html#if - Anthony Hatzopoulos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接