如果路径上的文件存在,Apache不会重写请求

时间:2011-09-20 09:32:37

标签: apache mod-rewrite

我正在使用mod_rewrite对每个与现有文件或目录不匹配的请求进行重写。这是我的配置:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.php [NC,L]

这用于将/abc/foo/abc/foo/10等网址映射到我的应用。它运作得很好。

为了提高性能,我的应用程序现在将/abc/foo的调用结果存储在相应目录foo中的文件/abc中 - 以便在第一次调用后重写条件不再应用(文件不存在),并且apache直接提供数据而无需先调用应用程序。工作正常。

问题是:请求/abc/foo/10现在不再导致URL被重写,而是收到错误“404 File Not Found”。日志条目表明重写条件!-f不再为真,但实际上文件/abc/foo/10 存在。 /abc/foo存在,但它是一个文件,而不是目录。

我怎样才能让它发挥作用?

(禁用MultiViews)

3 个答案:

答案 0 :(得分:4)

这是因为foo作为文件存在,而apache服务foo,其中附加/ 10作为查询字符串传递。因此,您的应用程序应该向foo文件写一些额外的代码,它还检查请求是否包含一些额外的url组件,然后处理目录的创建" foo"和文件10。

答案 1 :(得分:3)

您必须在per / dir / htaccess上下文中使用AcceptPathInfo。

因此REQUEST_FILENAME与现有的部分匹配,与REQUEST_URI不同。

如果您不关心请求先前在重写中的映射位置,请使用REQUEST_URI var。

在per-vh环境中,这些变量总是相同的。

答案 2 :(得分:2)

项目设计有点不对 - 其他人已经指出它不可扩展 - 如果已经有/ abc / foo文件,你怎么能将请求缓存到/ abc / foo / 10?

对此问题的回答以及您的问题是使用子文件夹而不是文件。

而不是缓存结构:

/abc/foo
/abc/bar
 ...?

使用:

/abc/index.html
/abc/foo/index.html
/abc/bar/index.html
/abc/foo/10/index.html

并且每次使用index.html

创建新目录

这次Apache会发现有/ abc / foo文件夹但没有/ abc / foo / 10文件,所以RewriteCond会适用。

修改

您也可以尝试不同的方式 - 使用mod_rewrite修改网址,更改网址:

/abc/foo
/abc/bar
/abc/foo/10

类似于:

/cache/abc~foo
/cache/abc~bar
/cache/abc~foo~10

htaccess规则(粗略地):

# redirecting to cache folder and removing last '/'
RewriteCond %{REQUEST_URI} ^/(abc|cde)
RewriteRule ^(.*?)/?$ /cache/$1 [L]

# recursive replacing '/' with '~'
RewriteCond %{REQUEST_URI} ^/cache/.*/
RewriteRule cache/(.*)/(.*)$ /cache/$1~$2 [L]

您的标准htaccess规则应遵循