0

这是我的配置:

  • http://domain.com(显然是虚构的名称...)托管在运行 Apache 且启用了 mod_rewrite 的服务器上
  • 名为“foo”的文件夹:(位于http://domain.com/foo/并且我想在其中放置我的 .htaccess 文件)仅包含 3 种类型的文件 .php、.htm、.html
    • .php 文件(为了示例,我将引用其中之一:phpfile.php)
    • .htm 文件(为了示例,我将引用其中之一:htmfile.htm)
    • .html 文件(为了示例,我将引用其中之一:htmlfile.html)
  • 在 foo 文件夹中,没有文件具有另一个扩展名或没有扩展名的等价文件(例如,foo 中既不存在 phpfile.htm 也不存在 phpfile.html 也不存在 phpfile,只有 php.file.php 存在)

这是我想要实现的目标:

我一直在努力,到目前为止,我已经为我的 .htaccess 文件(位于“foo”文件夹中)提供了这个内容,不幸的是,它只适用于我感兴趣的两种情况中的最后一种(即当我请求“phpfile”时服务“phpfile.php”,当我请求“htmfile”时服务“htmfile.htm”或当我请求“htmlfile”时服务“htmlfile.html”),并且忽略301重定向:

Options +FollowSymLinks
RewriteEngine on
RewriteBase /foo

# Redirect permanently the requests for existing .php files
# to extensionless files (non present on the server)
# so that phpfile.php gets redirected to phpfile
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} \.php$
RewriteCond %{REQUEST_FILENAME}\.php -f 
RewriteRule (.*)\.php$ $1   [R=301,NC]

# Redirect permanently the requests for existing .htm(l) files
# to extensionless files (non present on the server)
# so that htmfile.htm gets redirected to htmfile
# so that htmlfile.html gets redirected to htmlfile
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} \.html?$
RewriteCond %{REQUEST_FILENAME}\.html? -f   
RewriteRule (.*)\.html?$ $1 [R=301,NC]

# Matching requests for non existing extensionless files
# with their existing equivalent on the server
# so that domain.com/foo/phpfile will display
# the contents of domain.com/foo/phpfile.php,
RewriteCond %{REQUEST_FILENAME}\.php -f 
RewriteRule (.*)$ $1.php    [L]

# so that domain.com/foo/htmlfile will display
# the contents of domain.com/foo/htmlfile.html,
RewriteCond %{REQUEST_FILENAME}\.html -f    
RewriteRule (.*)$ $1.html   [L]

# so that domain.com/foo/htmfile will display
# the contents of domain.com/foo/htmfile.htm,
RewriteCond %{REQUEST_FILENAME}\.htm -f 
RewriteRule (.*)$ $1.htm    [L]

提前感谢您的任何帮助/建议。

4

2 回答 2

3

前两条规则存在逻辑缺陷,因为它是存在的 php 或 html 文件。URI 检查实际上也是重写规则模式的副本,!f 意味着 !-d。您还可以将它们折叠成一条规则:

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*?)\.(php|html?)$        $1   [R=301,NC]

最后两个没问题,但如果 html 请求比 php 更常见,我会交换顺序

为什么 MultiViews 没有帮助

Options +MultiViews实现了一个称为内容协商的概念,在此过程中,Apache 调用子查询来解析文件名根名称。它所做的其中一件事是扫描目录以查找已知的 filename.extension 组合,因此在这种情况下,如果xxx.php存在并且您的请求是针对的,xxx那么它将替换xxx.php并执行内部重定向,然后触发您的第一个规则,删除.php扩展名,这会导致您看到的错误。

所以(i)你需要禁用多视图,和(ii)同上子查询;(iii) 检测并防止重试循环。这是一种解决方案,可以满足您的需求:

Options +FollowSymLinks  -MultiViews
RewriteEngine on
RewriteBase /foo

RewriteCond %{ENV:REDIRECT_END}  =1
RewriteRule ^ - [L,NS]

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*?)\.(php|html?)$        $1   [R=301,NC,NS]

RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule (.*)$ $1.html   [L,E=END:1,NS]

RewriteCond %{REQUEST_FILENAME}\.htm -f
RewriteRule (.*)$ $1.htm    [L,E=END:1,NS]

RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule (.*)$ $1.php    [L,E=END:1,NS]
于 2012-02-06T11:54:30.817 回答
0

我要感谢每个人的这篇文章,因为它真的对我帮助很大,我使用了类似下面的东西并为我工作......

Options +FollowSymLinks  -MultiViews
RewriteEngine on
RewriteBase /

RewriteCond %{ENV:REDIRECT_END}  =1
RewriteRule ^ - [L,NS]

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^(.*?)\.(php|html?)$        $1   [R=301,NC,NS]

RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule (.*)$ $1.html   [L,E=END:1,NS]

RewriteCond %{REQUEST_FILENAME}\.htm -f
RewriteRule (.*)$ $1.htm    [L,E=END:1,NS]

RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule (.*)$ $1.php    [L,E=END:1,NS]

这个版本适合我。

谢谢你。

干杯!

于 2013-11-22T05:22:53.063 回答