mod 重写以删除文件扩展名、添加尾部斜杠、删除 www 并在没有文件/目录可用时重定向到 404 [英] mod rewrite to remove file extension, add trailing slash, remove www and redirect to 404 if no file/directory is available

查看:21
本文介绍了mod 重写以删除文件扩展名、添加尾部斜杠、删除 www 并在没有文件/目录可用时重定向到 404的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I would like to create rewrite rules in my .htaccess file to do the following:

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

  • When accessed via domain.com/abc.php: remove the file extension, append a trailing slash and load the abc.php file. url should look like this after rewrite: domain.com/abc/

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

When accessed via domain.com/abc/: leave the url as is and load abc.php

当通过 domain.com/abc 访问时:附加尾部斜杠并加载 abc.php.重写后的 url 应如下所示:domain.com/abc/

When accessed via domain.com/abc: append trailing slash and load abc.php. url should look like this after rewrite: domain.com/abc/

删除 www

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

Redirect to 404 page (404.php) when accessed url doesn't resolve to folder or file, e.g. when accessing either domain.com/nothingthere.php or domain.com/nothingthere/ or domain.com/nothingthere

进行一些从旧网址到新网址的永久性 301 重定向(例如 domain.com/abc.html 到 domain.com/abc/)

Make some permanent 301 redirects from old urls to new ones (e.g. domain.com/abc.html to domain.com/abc/)

所有 php 文件都位于文档根目录中,但是如果有一种解决方案可以使诸如 domain.com/abc/def/(将加载 domain.com/abc/def.php)之类的 url 也可以使用它也很棒,但不是必需的

All php files sit in the document root directory, but if there is a solution that would make urls such as domain.com/abc/def/ (would load domain.com/abc/def.php) also work it would be great as well, but not necessary

这就是我目前所拥有的(从各种来源和网络上的样本收集起来

So here is what I have at the moment (thrown together from various sources and samples from around the web

<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,最终的 url 总是以 domain.com/abc/结束并加载了 domain.com/abc.php.

With this the first four requirements seem to work, whether I enter domain.com/abc.php, domain.com/abc/ or domain.com/abc, the final url always ends up being domain.com/abc/ and domain.com/abc.php is loaded.

当我输入解析为不存在的文件的 url 时,我收到错误 310(重定向循环),实际上应该加载 404 页面.此外,我还没有尝试过子文件夹是否工作,但正如我所说,这是低优先级.我很确定我可以在没有任何问题的情况下为旧版 url 设置永久 301 重定向,只是想提一下.所以真正的问题是无法正常工作的 404 页面.

When I enter a url that resolves to a file that doesn't exists I'm getting an error 310 (redirect loop), when really a 404 page should be loaded. Additionally I haven't tried if subfolders work, but as I said, that's low priority. I'm pretty sure I can just slap the permanent 301 redirects for legacy urls on top of that without any issues as well, just wanted to mention it. So the real issue is really the non working 404 page.

推荐答案

我在让 ErrorDocument 在重写错误时可靠地工作时遇到了问题,所以我倾向于在重写级联中正确处理无效页面.我试图用这个覆盖所有的测试向量.没有发现任何缺口.

I've had problems with getting ErrorDocument to work reliably with rewrite errors, so I tend to prefer to handle invalid pages correctly in my rewrite cascade. I've tried to cover a fully range of test vectors with this. Didn't find any gaps.

一些一般要点:

  • 您需要在此使用 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,但额外的逻辑也可以选择这一点.
  • You need to use the DOCUMENT_ROOT environment variable in this. Unfortunately if you use a shared hosting service then this isn't set up correctly during rewrite execution, so hosting providers set up a shadow variable to do the same job. Mine uses DOCUMENT_ROOT_REAL, but I've also come across PHP_DOCUMENT_ROOT. Do a phpinfo to find out what to use for your service.
  • There's a debug info rule that you can trim as long as you replace DOCROOT appropriately
  • You can't always use %{REQUEST_FILENAME} where you'd expect to. This is because if the URI maps to DOCROOT/somePathThatExists/name/theRest then the %{REQUEST_FILENAME} is set to DOCROOT/somePathThatExists/name rather than the full pattern equivalent to the rule match string.
  • This is "Per Directory" so no leading slashes and we need to realise that the rewrite engine will loop on the .htaccess file until a no-match stop occurs.
  • This processes all valid combinations and at the very end redirects to the 404.php which I assume sets the 404 Status as well as displaying the error page.
  • It will currently decode someValidScript.php/otherRubbish in the SEO fashion, but extra logic can pick this one up as well.

所以这里是 .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]

享受:-)

这篇关于mod 重写以删除文件扩展名、添加尾部斜杠、删除 www 并在没有文件/目录可用时重定向到 404的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆