我在根 Web 目录中的 .htaccess 文件中使用 mod_rewrite,以便我们可以在某些特定情况下使用更干净的 URL。例如,我们想要翻译:
http://example.com/Topic/ABCD/Type/Description
进入
http://example.com/Topic.php?l=ABCD&e=Type&t=Description
这看起来很容易;.htaccess 文件由以下部分组成:
RewriteEngine on
RewriteRule ^Topic/([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ /Topic.php?l=$1&e=$2&t=$3 [L]
但是,页面的所有内容(.CSS 文件、图像等)最终都以 404 错误结束,因为不是从相对于重写的 URL 的目录加载“/Common.css”:
http://example.com/Common.css
它从未重写的 URL 目录中加载它:
http://example.com/Topic/ABCD/Type/Description/Common.css
这显然不存在。但是,我发现网络上有无数教程提倡我所做的事情的一些变体(一个例子这里),但没有提到我遇到的这个问题,所以我想知道我是否只是忽略了一些配置。它们不能都依赖于这些“虚拟”目录的存在并包含页面的内容。我也不想把所有东西都变成绝对路径。
我曾尝试在 .htaccess 文件中添加规则,以尝试短路内容请求,例如:
RewriteRule \.(css|jpe?g|gif|png)$ - [L]
但似乎没有效果。无论如何,我没想到这样的内容会符合原始规则,因为该规则中的正则表达式不允许在(可选的)尾部斜杠后面出现任何内容。
如果我更改规则,使其标志设置为重定向([R,L] 而不是 [L]),那么一切都会正常进行 — — 只是现在浏览器会显示重写的 php 参数字符串,而这正是我们试图避免的。过去,我们只是接受了这种解决方法,但现在我试图理解为什么它会这样工作,以及我能做些什么。
如果相关的话,我正在使用 CentOS 6.2 和 Apache/2.2.15。
答案1
问题很可能是你的代码生成的页面包含如下 CSS:
<link rel="stylesheet" type="text/css" href="Common.css" />
由于浏览器看到了这一点,并将其获取的 URL 视为子路径,因此它会在该子路径上请求 Common.css。
您可以(但不应该,原因我稍后会解释)制定更多的重写规则,将 Common.css 等重写为顶层的单个规则,例如:
RewriteRule上的 RewriteEngine
^Topic/([^/.]+)/([^/.]+)/([^/.]+)/Common.css$ /Common.css [L]
然而,这样做很愚蠢,因为 CSS 的全部意义在于允许缓存等。一个更好的方法是简单地在代码中的 Common.css 前面添加一个 /,这样它就会产生如下 CSS:
<link rel="stylesheet" type="text/css" href="/Common.css" />
这样,所有页面都使用相同的 Common.css 文件,并且浏览器不必在每个页面的多个逻辑位置获取相同文件的副本,而且浏览器知道在顶层而不是子页面上获取它。
PS Jakub:RewriteRule 的正则表达式已经排除了其中带有句点的任何内容,其中已经涵盖了 .css、.jpg 等,因此添加额外的 RewriteCond 无济于事。
答案2
您必须使用 RewriteCond
RewriteEngine on
RewriteCond $1 !^(\.css|\.js|\.png|\.jpg)
RewriteRule ^Topic/([^/\.]+)/([^/\.]+)/([^/\.]+)/?$ /Topic.php?l=$1&e=$2&t=$3 [L]
答案3
答案相对简单 - 您必须在 html 代码中使用 base href,因为重写 URI 的过程会重置 Base URL,从而导致您遇到的 404 错误。
有一篇关于此问题的好文章http://pixelcode.co.uk/tutorials/Clean+URLs+with+mod_rewrite.html
问候 Miles