2

我想在我的.htaccess文件创建重写规则执行以下操作:国防部重写删除文件扩展名,添加斜线,删除www和重定向到404,如果没有文件/目录可用

  • 当通过domain.com/abc.php进行访问时:删除文件扩展名,附加斜杠并加载abc.php文件。网址应该是这样的,修改后:domain.com/abc/

  • 当通过domain.com/abc/访问:保留原样的URL和负载abc.php

  • 当通过domain.com访问/ abc:追加尾部斜杠并加载abc.php。网址应该是这样的,修改后:domain.com/abc/

  • 删除WWW

  • 重定向到404页(404.php)当访问网址无法解析为文件夹或文件,例如当访问domain.com/nothingthere.php或domain.com/nothingthere/或domain.com/nothingthere

  • 使某些永久301从旧网址重定向到新网址(例如,domain.com/abc.html到域.COM/ABC /)

所有PHP文件坐在文档根目录,但如果有一个解决方案,将使网址,如domain.com/abc/def/(将加载domain.com/ abc/def.php)也能工作,它也会很好,但并不是必需的

所以这里是我现在所拥有的(从各种来源和样本网络

<IfModule mod_rewrite.c> 
    RewriteCond %{HTTPS} !=on 
    # redirect from www to non-www 
    RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] 
    RewriteRule^http://%1%{REQUEST_URI} [R=301,L] 

    # remove php file extension 
    RewriteCond %{REQUEST_FILENAME} !-d 
    RewriteCond %{THE_REQUEST} ^GET\ /[^?\s]+\.php 
    RewriteRule (.*)\.php$ /$1/ [L,R=301] 

    # add trailing slash 
    RewriteCond %{REQUEST_FILENAME} !-f 
    RewriteRule ^.*[^/]$ /$0/ [L,R=301] 

    # resolve urls to matching php files 
    RewriteCond %{REQUEST_FILENAME} !-d 
    RewriteRule (.*)/$ $1.php [L] 

有了这个第一四点要求似乎工作,我是否进入domain.com/abc.php,domain.com/abc/或domain.com/abc,最终网址始终最终被加载为domain.com/abc/和domain.com/abc.php。

当我输入一个url解析为不存在的文件时,我收到一个错误310(重定向循环),当真的应该加载404页面。此外,我还没有尝试过,如果子文件夹的工作,但正如我所说,这是低优先级。我非常肯定,我可以在没有任何问题的情况下对传统网址进行永久301重定向,只是想提一提。所以真正的问题是非工作404页面。

回答

5

我得到ErrorDocument与重写错误可靠地工作的问题,所以我倾向于在我的重写级联中正确处理无效页面。我试图用这个覆盖全面的测试向量。没有找到任何差距。

一些一般性的要点:

  • 您需要使用DOCUMENT_ROOT环境变量在此。不幸的是,如果您使用共享托管服务,则在重写执行期间没有正确设置,因此托管提供程序会设置一个影子变量来执行相同的工作。我使用DOCUMENT_ROOT_REAL,但我也遇到过PHP_DOCUMENT_ROOT。做一个phpinfo找出你的服务使用什么。
  • 没有为你更换DOCROOT适当
  • 你不能总是用%{REQUEST_FILENAME}这里,你希望是一个调试信息的规则,你可以,只要修剪。这是因为如果URI映射到DOCROOT/somePathThatExists/name/theRest那么%{REQUEST_FILENAME}设置为DOCROOT/somePathThatExists/name而不是与规则匹配字符串等效的完整模式。
  • 这是“每个目录”,所以没有引导斜杠,我们需要认识到,重写引擎将在.htaccess文件上循环,直到发生不匹配停止。
  • 这处理所有有效的组合,并在最后重定向到404.php,我假设设置404状态以及显示错误页面。
  • 目前它将在SEO时尚中解码someValidScript.php/otherRubbish,但额外的逻辑也可以选择这个。

因此,这里的.htaccess片段:

Options -Indexes -MultiViews 
AcceptPathInfo Off 

RewriteEngine On 
RewriteBase /

## Looping stop. Not needed in Apache 2.3 as this introduces the [END] flag 
RewriteCond %{ENV:REDIRECT_END} =1 
RewriteRule^     -      [L,NS] 

## 302 redirections ## 

RewriteRule^- [E=DOCROOT:%{ENV:DOCUMENT_ROOT_REAL},E=URI:%{REQUEST_URI},E=REQFN:%{REQUEST_FILENAME},E=FILENAME:%{SCRIPT_FILENAME}] 

# redirect from HTTP://www to non-www 
RewriteCond %{HTTPS} !=on 
RewriteCond %{HTTP_HOST}  ^www\.(.+)$ [NC] 
RewriteRule^     http://%1%{REQUEST_URI} [R=301,L] 

# remove php file extension on GETs (no point in /[^?\s]+\.php as rule pattern requires this) 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteCond %{REQUEST_METHOD} =GET 
RewriteRule (.*)\.php$   $1/      [L,R=301] 

# add trailing slash 
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteRule ^.*[^/]$   $0/      [L,R=301] 

# terminate if file exists. Note this match may be after internal redirect. 
RewriteCond %{REQUEST_FILENAME} -f 
RewriteRule^     -      [L,E=END:1] 

# terminate if directory index.php exists. Note this match may be after internal redirect. 
RewriteCond %{REQUEST_FILENAME} -d 
RewriteCond %{ENV:DOCROOT}/$1/index.php -f 
RewriteRule ^(.*)(/?)$    $1/index.php   [L,NS,E=END:1] 

# resolve urls to matching php files 
RewriteCond %{ENV:DOCROOT}/$1.php -f 
RewriteRule ^(.*?)/?$    $1.php    [L,NS,E=END:1] 

# Anything else redirect to the 404 script. This one does have the leading/

RewriteRule^     /404.php    [L,NS,E=END:1] 

享受:-)

+0

您能解释'RewriteCond%{ENV:DOCROOT}/$ 1/index.php -f'中的'$ 1'的含义吗? – Filkor 2012-04-03 00:07:46

+0

执行顺序是:rule.regexp; COND1; cond2; ... rule.substitution。变量'$ 1' ...是正则表达式中的匹配模式,可用于conds。在这种情况下,作为URI的'(。*)'内容不会有任何尾随/。 – TerryE 2012-04-06 16:30:54

0

您可能想在添加尾部斜杠之前检查php文件是否存在。

RewriteCond %{REQUEST_FILENAME} !-f 
RewriteCond %{REQUEST_FILENAME}.php -f 
RewriteRule ^.*[^/]$ /$0/ [L,R=301] 

,或者如果你真的想为所有404页拖尾斜杠(所以/image/error.jpg将成为/images/error.jpg/,我认为这是奇怪的):

RewriteCond %{ENV:REDIRECT_STATUS} !200 
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteRule ^.*[^/]$ /$0/ [L,R=301] 
0

我想出了这一点:

DirectorySlash Off 
RewriteEngine on 
Options +FollowSymlinks 

ErrorDocument 404 /404.php 

#if it's www 
# redirect to non-www. 
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] 
    RewriteRule^http://%1%{REQUEST_URI} [L,R=301,QSA] 

#else if it has slash at the end, and it's not a directory 
# serve the appropriate php 
RewriteCond %{ENV:REDIRECT_STATUS} ^$ 
RewriteCond %{REQUEST_FILENAME} !-d 
    RewriteRule ^(.*)/$ /$1.php [L,QSA] 

#else if it's an existing file, and it's not php or html 
# serve the content without rewrite 
RewriteCond %{ENV:REDIRECT_STATUS} ^$ 
RewriteCond %{REQUEST_FILENAME} -f 
RewriteCond %{REQUEST_URI} !(\.php)|(\.html?)$ 
    RewriteRule^- [L,QSA] 

#else 
# strip php/html extension, force slash 
RewriteCond %{ENV:REDIRECT_STATUS} ^$ 
    RewriteRule ^(.*?)((\.php)|(\.html?))?/?$ /$1/ [L,NC,R=301,QSA] 

当然不是很优雅(环境:redirect_status是相当黑客),但它通过我的适度测试。不幸的是,我无法测试www重定向,因为我在本地主机上,并且没有真正的服务器访问权限,但该部分也应该可以工作。

您会看到,我使用了ErrorDocument指令来指定错误页面,并使用DirectorySlash Off请求来确保Apache不会干扰slash追加的乐趣。我还使用了QSA(查询字符串追加)标志,它将查询字符串附加到请求中,以便它不会丢失。无论如何,它在尾部斜线后看起来有点愚蠢。

否则它非常简单,我认为这些评论很好地解释了它。如果您遇到任何问题,请告诉我。

0
  1. 域的根
  2. 放置一个的.htaccess上述文件夹下创建一个文件夹as RewriteRule^$ index.php
  3. 解析URL
  4. 使用PHP编码,您现在可以根据需要去除URL或文件扩展名
相关问题