mod重写删除文件扩展名,添加尾部斜杠,删除www并重定向到404,如果没有文件/目录可用

xim*_*imi 2 url .htaccess mod-rewrite url-rewriting http-status-code-404

我想在我的.htaccess文件中创建重写规则来执行以下操作:

  • 通过domain.com/abc.php访问时:删除文件扩展名,附加一个尾部斜杠并加载abc.php文件.重写后url应如下所示:domain.com/abc/

  • 通过domain.com/abc/访问时:保留原样并加载abc.php

  • 通过domain.com/abc访问时:追加尾随斜杠并加载abc.php.重写后url应如下所示:domain.com/abc/

  • 删除www

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

  • 将一些永久的301重定向从旧网址转换为新网址(例如domain.com/abc.html到domain.com/abc/)

所有的php文件都位于文档根目录中,但如果有一个解决方案可以使域名(如果加载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]
Run Code Online (Sandbox Code Playgroud)

有了这个,前四个要求似乎有效,无论我输入domain.com/abc.php,domain.com/abc/还是domain.com/abc,最终的URL总是最终成为domain.com/abc/和domain. com/abc.php已加载.

当我输入一个解析为不存在的文件的URL时,我收到错误310(重定向循环),当真正加载404页面时.另外,如果子文件夹工作,我没有尝试过,但正如我所说,这是低优先级.我很确定我可以在没有任何问题的情况下为传统网址重新发送永久301重定向,只是想提及它.所以真正的问题实际上是非工作的404页面.

Ter*_*ryE 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]
Run Code Online (Sandbox Code Playgroud)

请享用 :-)