我对这个重写规则有一个奇怪的情况:
RewriteCond img/$2/$3/$4/$1 -f
RewriteRule ^img/(([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]{4})[a-z0-9]{28}\.\w+)$ img/$2/$3/$4/$1 [L]
其目录结构如下(简化):
var/
images/
..
www/
.htaccess
img -> /var/images
换句话说,图像存储在 webroot 之外的通用数据存储区域中,并img
通过符号链接链接到 webroot 的目录中。图像名称是哈希值。为了提高效率,它们存储在三级深层目录层次结构中。例如:
0a808e34edaaeeffd973e4138789a4957d6b6a26.jpg
存储在
images/0a80/8e34/edaa/0a808e34edaaeeffd973e4138789a4957d6b6a26.jpg
重写规则只是将文件名重写到嵌套目录结构中。
现在,奇怪的是,RewriteCond
在我的本地系统上运行良好,但在测试服务器上却失败了。Apache 调试日志明确指出,-f
这种情况下的“模式不匹配”。如果我简单地删除这个条件,重写规则就可以正常工作,并且可以提供图像。
什么可能导致-f
明明存在的文件失败?
FollowSymLinks
是允许的。Apache 版本 2.2.22-6ubuntu2 通过 apt 安装,几乎没有修改。在本地安装的 Apache 2.2.23 上工作(通过 homebrew)。没有看到任何显著的变化这两个版本之间应该会导致这种情况。
关于实际目录结构的一些可能更重要的细节:
$ ls -l /var/www/myapp/current
[snip] /var/www/myapp/current -> /var/www/myapp/releases/20130418090750
$ ls -la /var/www/myapp/current/webroot
[snip]
[snip] .htaccess
[snip] img -> /usr/local/var/myapp/images
Apache webroot 配置为:
DocumentRoot /var/www/myapp/current/webroot
如果我将其写RewriteCond
为:
RewriteCond /usr/local/var/myapp/images/$2/$3/$4/$1 -f
它可以工作。但如果可以避免的话,我宁愿不硬编码绝对路径。
Apache 是否会对多个级别的符号链接感到困惑?
答案1
实际上,我还没有看到过一篇文章有关于RewriteCond
从下面获取变量的教程。但是,您仍然可以尝试在顶部RewriteRule
添加一个指令RewriteBase
.htaccess文件:
RewriteBase /www/
或者这样,都尝试一下:
RewriteBase /var/www/
或者你可以尝试下面这些指令集之一,但是排除上面列出的任何RewriteBase
指令:
RewriteCond /www/img/$2/$3/$4/$1 -f
RewriteRule ^www/img/(([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]{4})[a-z0-9]{28}\.\w+)$ /www/img/$2/$3/$4/$1 [L]
或者你甚至可以尝试一下:
RewriteCond /var/www/img/$2/$3/$4/$1 -f
RewriteRule ^var/www/img/(([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]{4})[a-z0-9]{28}\.\w+)$ /var/www/img/$2/$3/$4/$1 [L]
很抱歉抄袭了你的重写条件和规则的格式,因为你说过“它在您的本地开发系统上运行。”但如果你只是想重写,这是我向你推荐的简单规则/$var1.$var2进入/图像/0a80/8e34/edaa/$var1.$var2,你甚至可以逐个静态添加其他内容:
RewriteRule ^([a-zA-Z0-9_-]+).([a-zA-Z]{3})$ /images/0a80/8e34/edaa/$var1.$var2
或者如果你想重写,你甚至可以尝试这个/img/0a808e34edaaeeffd973e4138789a4957d6b6a26.jpg动态地进入/img/0a80/8e34/edaa/0a808e34edaaeeffd973e4138789a4957d6b6a26.jpg如果重新映射的动态 URL 是一个文件,则条件是:
RewriteCond /img/$2/$3/$4/$1\.$5 -f
RewriteRule ^img/(([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]{4})[a-z0-9]{28})\.([a-z]{3})$ /img/$2/$3/$4/$1.$5
请记住“0a80”,“8e34”和“埃达”必须精确到 4 和字符。“eeffd973e4138789a4957d6b6a26”必须是 28 并且“jpg”必须是 3。我希望这会起作用,但我怀疑..
答案2
如果它在 localhost 上运行良好,但在 test.com 上却不行,我猜是文件系统出了问题,或者与您可能认为理所当然的更一般的站点配置有关。您是否安装了两个操作系统,然后在两台机器上使用相同的过程安装了相同的软件包?每个 Apache 附带的默认配置是什么样的?在您查看之前修改了默认配置的软件包怎么样?
也许您的 Apache 版本非常相似,但如果它们来自不同的来源,默认配置可能有所不同,并且随后可能会进行不同的修改。从顶部开始验证您的配置。有什么不同?尝试使它们看起来完全相同(不仅是您的重写,还包括虚拟主机或服务器上下文。)
您的 Rewrite 指令的上下文可能会有所帮助(因为我认为这是范围问题)。重写是在 VirtualHost、Document-Root 还是 Directory 上下文中?
我从你的帖子中看到的成功与失败之间的最大区别是:
相对的
RewriteCond img/$2/$3/$4/$1 -f
绝对
RewriteCond /usr/local/var/myapp/images/$2/$3/$4/$1 -f
Apache 能够找到该文件,因此不应该是权限问题或类似问题。您是否使用了任何 Alias 指令(localhost 与 test.com)?如果没有,也许您应该尝试专门为此设置 Alias:
/var/www/myapp/当前-> /var/www/myapp/releases/20130418090750
在根配置中放置至少一个不需要符号链接的硬路径。您可以在目录上下文中完成重写...
<Directory /var/www/myapp/current/webroot>
rewrite statements...
</Directory>
如果您在 test.com 上维护损坏的配置,但目前有符号链接,请尝试从根目录开始(临时)复制实际目录。只需验证没有浮动的松散符号链接设置。删除尽可能多的符号链接,然后逐个将其放回。
答案3
反向引用是“up”(rewriteCond)到“down”(RewriteRule)。在您发布的示例中,就像是“down”到“up”。并且,反向引用是用%表示的,而不是用$表示。
RewriteCond 反向引用:这些是形式为 %N(0 <= N <= 9)的反向引用。%1 到 %9 提供对模式的分组部分(同样在括号中)的访问,从当前条件集中最后匹配的 RewriteCond 开始。%0 提供对该模式匹配的整个字符串的访问。
你可以尝试这个:
RewriteBase /
RewriteCond %{REQUEST_URI} /img/([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]{4})([a-z0-9]{28}\.\w+)$
RewriteCond %{DOCUMENT_ROOT}/test/%1/%2/%3/%4 -f
RewriteRule .* img/%1/%2/%3/%4 [L]
首先使用正则表达式查找变量。构造包含变量的文件的路径,并验证文件是否存在
我用%{文档根目录}用于在本地服务器上进行测试。如果您没有在同一个 DocumentRoot 中保存此图像文件,则需要完整路径喜欢:
RewriteCond /var/www/cache_images/test/%1/%2/%3/%4 -f