这个重写规则有一个奇怪的场景:
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之外,并通过符号链接链接到webroot的img目录中。 图像名称是散列。 为了提高效率,它们被存储在三层深的目录层次结构中。 例如:
0a808e34edaaeeffd973e4138789a4957d6b6a26.jpg
存储在
images/0a80/8e34/edaa/0a808e34edaaeeffd973e4138789a4957d6b6a26.jpg
重写规则只是将文件名重写为嵌套的目录结构。
现在,奇怪的是, RewriteCond在我的本地系统上正常工作,但在testing服务器上失败。 Apachedebugging日志明确指出,“- -f模式不匹配”这种情况。 如果我只是删除这个条件重写规则工作正常,图像被送达。
什么可能导致-f文件显然存在失败?
FollowSymLinks是允许的。 Apache版本2.2.22-6ubuntu2通过apt安装,几乎没有修改。 在Apache 2.2.23的本地安装上工作(通过自制软件)。 在这两个版本之间看不到任何重大的变化 。
关于实际目录结构的一些更可能的重要细节:
$ 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被configuration为:
DocumentRoot /var/www/myapp/current/webroot
如果我把RewriteCond写成:
RewriteCond /usr/local/var/myapp/images/$2/$3/$4/$1 -f
有用。 我宁愿不硬编码绝对path,尽pipe如果可以避免的话。
可能Apache会被几个级别的符号链接混淆?
实际上,我从来没有看到有一篇文章有关于RewriteCond的教程来从它下面的RewriteRule中获取一个variables。但是,您仍然可以尝试在.htaccess文件的顶部添加一个RewriteBase指令:
RewriteBase /www/
或者,这只是一个尝试:
RewriteBase /var/www/
或者你可以尝试下面这些指令集中的一个,但不RewriteBase上面列出的任何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放到/images/0a80/8e34/edaa/$var1.$var2中 ,你甚至可以一个接一个的静态添加其他的:
RewriteRule ^([a-zA-Z0-9_-]+).([a-zA-Z]{3})$ /images/0a80/8e34/edaa/$var1.$var2
或者你甚至可以尝试这个,如果你想重写/img/0a808e34edaaeeffd973e4138789a4957d6b6a26.jpgdynamic到/img/0a80/8e34/edaa/0a808e34edaaeeffd973e4138789a4957d6b6a26.jpg条件如果它重新映射的dynamicURL是一个文件:
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})\.([az]{3})$ /img/$2/$3/$4/$1.$5
请记住, “0a80” , “8e34”和“edaa”上的字符必须精确为4和字符。 在“eeffd973e4138789a4957d6b6a26”必须为28,在“JPG”必须为3.我希望这会工作,但我怀疑..
如果它在localhost上,而不是在test.com上,我会猜测它是你的文件系统的一个问题,或者它与你认为理所当然的更一般的站点configuration有关。 你是否安装了两个操作系统,然后安装相同的包,在两台机器上使用相同的过程? 每个Apache的每个默认configuration看起来像什么? 那么在你看完之前修改默认configuration的软件包呢?
也许你的apache版本差不多,但是如果它们来自不同的来源,默认的configuration可能会有所不同,可能会有不同的修改。 validation您的configuration从顶部开始。 有什么不同吗? 试着让它们看起来完全一样(不只是你的重写,而是虚拟主机或服务器上下文)。
你的Rewrite指令的上下文可能会有帮助(因为我认为这是一个范围问题)。 是否在VirtualHost,Document-Root,Directory上下文中重写?
我从你的post看成功与失败之间最大的区别是:
相对的
RewriteCond img/$2/$3/$4/$1 -f
绝对
RewriteCond /usr/local/var/myapp/images/$2/$3/$4/$1 -f
Apache能够find该文件,所以它不应该是权限或任何这样的。 你是否使用任何Alias指令(localhost vs test.com)? 如果没有,也许你应该尝试别名这个具体:
/ var / www / myapp / current – > / var / www / myapp / releases / 20130418090750
在根configuration中至less放置一个不需要符号链接的硬path。 您可以在目录上下文中重写您的重写…
<Directory /var/www/myapp/current/webroot> rewrite statements... </Directory>
如果你在test.com上维护你的破损configuration,但是你现在有符号链接的地方,试着从根目录开始复制实际的目录(暂时)。 只要validation是否有一些松散的符号链接设置浮动。 摆脱尽可能多的符号链接,并把它们放回1 1。
反向引用是“up”(rewriteCond)到“down”(RewriteRule)。 在你发布的例子中,就像“下”到“上”。 而且, 反向引用是用%而不是$。
RewriteCond反向引用:这些是%N(0 <= N <= 9)forms的反向引用。 %1到%9提供对当前条件集合中最后一个匹配的RewriteCond的模式分组部分(同样在括号内)的访问。 %0提供对该模式匹配的整个string的访问。
你可以试试这个:
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]
首先是正则expression式来查找variables。 如果文件存在,则构build包含variables的文件path并进行validation
我在本地服务器上使用%{DOCUMENT_ROOT}进行testing。 如果你没有这个图像文件在同一个DocumentRoot你需要像这样的完整path :
RewriteCond /var/www/cache_images/test/%1/%2/%3/%4 -f