通过隐藏.php和.htm(l)扩展并重定向到无扩展名URL来强制重写URL

时间:2012-02-06 08:11:35

标签: .htaccess url-rewriting clean-urls

这是我的配置:

  • 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]

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

2 个答案:

答案 0 :(得分:3)

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

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

最后两个是好的,但如果html请求比php

更常见,我会交换订单

为什么MultiViews无法帮助

Options +MultiViews实现了一个名为content negotiation的概念,在执行此操作时,Apache会调用子查询来解析文件名根名称。它所做的一件事是扫描目录中已知的filename.extension组合,所以在这种情况下,如果xxx.php存在并且您的请求是xxx,那么它将替换 xxx.php < / strong>并执行内部重定向,然后导致您的第一个规则触发,删除 .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]

答案 1 :(得分: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]

此版本适合我。

谢谢。

干杯!