Apache 复杂(?)htaccess重写/重定向

Apache 复杂(?)htaccess重写/重定向,apache,.htaccess,redirect,mod-rewrite,Apache,.htaccess,Redirect,Mod Rewrite,似乎每隔几周我就要问更多。htaccess重写/重定向问题。每次我认为自己理解了它,我的项目中就会有另一把扳手,这表明我不理解 编辑:我最初的问题不是很清楚,所以下面是一个更简洁的尝试 目前,所有的.html文件都位于根目录中。例如:http://example.com/about.html RewriteRule /$ /index.html [L] 除了img、css等普通子目录外,没有任何子目录 出于跟踪目的,如果有人键入http://example.com/random/如果“rand

似乎每隔几周我就要问更多。htaccess重写/重定向问题。每次我认为自己理解了它,我的项目中就会有另一把扳手,这表明我不理解

编辑:我最初的问题不是很清楚,所以下面是一个更简洁的尝试

目前,所有的.html文件都位于根目录中。例如:
http://example.com/about.html

RewriteRule /$ /index.html [L]
除了img、css等普通子目录外,没有任何子目录

出于跟踪目的,如果有人键入
http://example.com/random/
如果“random”可以是任何字符串,我希望他们在不修改url的情况下查看
index.html
文件。服务器上根本不存在“random”目录

其他页面也一样,比如
about.html
。如果有人输入
http://example.com/random/about.html
我想让他们看到
关于.html
页面

同时,我想要
http://example.com/random/about
http://example.com/about
(缺少文件扩展名)以同时显示“关于”页面

但是,如果有人输入了一个不存在的页面,我希望它使用
ErrorDocument

示例:我没有名为“pickups.html”的文件,因此以下文件都是404:

http://example.com/pickups.html
http://example.com/pickups
http://example.com/random/pickups.html
http://example.com/random/pickups
如果end redirect/rewrite确实去掉了文件扩展名(因为它看起来更好),那就太好了

我的想法是,任何以
/
结尾的请求都只会提供存在于站点根目录中的index.html文件。这样就剩下文件了

我的思考过程是:

  • 从请求中删除文件扩展名
  • 检查站点根目录中是否存在扩展名为的文件
  • 如果是,则显示该页面
  • 如果没有,404
我最初的代码(有帮助)是这样的:

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)/(.*)$ /$2 [R=301,L]

我知道在那段代码中,我获取了最后一个斜杠之后的所有内容,并从文档根提供它。不幸的是,它没有考虑不存在的文件。

从现有文件开始,它们将以不变的方式传递。这也可以防止重写循环

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
接下来是现有文件,作为可选虚拟子目录的一部分进行请求

RewriteCond %{DOCUMENT_ROOT}/$2 -f
RewriteRule ^(.+/)?(.+)$ /$2 [L]

RewriteCond %{DOCUMENT_ROOT}/$2.html -f
RewriteRule ^(.+/)?(.+)$ /$2.html [L]
这将请求拆分为可选前缀
(.+/)?
和文件部分。如果此文件部分存在,可能会附加一个
.html
,那么就完成了

接下来是任何带有尾随斜杠的内容,只需重写为
index.html

RewriteRule /$ /index.html [L]
其他任何内容都是对不存在的文件的请求,这将生成一个
404
状态代码


为了删除现有文件的可选
.html
扩展名和可选尾部斜杠
/
,我们必须在开头插入两条规则

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{DOCUMENT_ROOT}/$2.html -f
RewriteRule ^(.+/)?(.+?)\.html/?$ /$1$2 [R,L]

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{DOCUMENT_ROOT}/$2.html -f
RewriteRule ^(.+/)?(.+?)/$ /$1$2 [R,L]
这些规则与其他规则类似,只是它们执行重定向而不是重写,并且具有防止重写循环的附加条件


把所有的东西放在一起

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{DOCUMENT_ROOT}/$2.html -f
RewriteRule ^(.+/)?(.+?)\.html/?$ /$1$2 [R,L]

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{DOCUMENT_ROOT}/$2.html -f
RewriteRule ^(.+/)?(.+?)/$ /$1$2 [R,L]

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]

RewriteCond %{DOCUMENT_ROOT}/$2 -f
RewriteRule ^(.+/)?(.+)$ /$2 [L]

RewriteCond %{DOCUMENT_ROOT}/$2.html -f
RewriteRule ^(.+/)?(.+)$ /$2.html [L]

RewriteRule /$ /index.html [L]

从现有文件开始,它们将以不变的方式传递。这也可以防止重写循环

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]
接下来是现有文件,作为可选虚拟子目录的一部分进行请求

RewriteCond %{DOCUMENT_ROOT}/$2 -f
RewriteRule ^(.+/)?(.+)$ /$2 [L]

RewriteCond %{DOCUMENT_ROOT}/$2.html -f
RewriteRule ^(.+/)?(.+)$ /$2.html [L]
这将请求拆分为可选前缀
(.+/)?
和文件部分。如果此文件部分存在,可能会附加一个
.html
,那么就完成了

接下来是任何带有尾随斜杠的内容,只需重写为
index.html

RewriteRule /$ /index.html [L]
其他任何内容都是对不存在的文件的请求,这将生成一个
404
状态代码


为了删除现有文件的可选
.html
扩展名和可选尾部斜杠
/
,我们必须在开头插入两条规则

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{DOCUMENT_ROOT}/$2.html -f
RewriteRule ^(.+/)?(.+?)\.html/?$ /$1$2 [R,L]

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{DOCUMENT_ROOT}/$2.html -f
RewriteRule ^(.+/)?(.+?)/$ /$1$2 [R,L]
这些规则与其他规则类似,只是它们执行重定向而不是重写,并且具有防止重写循环的附加条件


把所有的东西放在一起

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{DOCUMENT_ROOT}/$2.html -f
RewriteRule ^(.+/)?(.+?)\.html/?$ /$1$2 [R,L]

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{DOCUMENT_ROOT}/$2.html -f
RewriteRule ^(.+/)?(.+?)/$ /$1$2 [R,L]

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^ - [L]

RewriteCond %{DOCUMENT_ROOT}/$2 -f
RewriteRule ^(.+/)?(.+)$ /$2 [L]

RewriteCond %{DOCUMENT_ROOT}/$2.html -f
RewriteRule ^(.+/)?(.+)$ /$2.html [L]

RewriteRule /$ /index.html [L]

测试可以通过本地Apache安装轻松完成。添加PHP来查看环境,但大多数情况下,一个普通的Apache就足够了。在研究了这一点之后,我必须承认,我甚至不理解您想要什么。我建议把它分成小块,一步一步地解决你的问题。我有一个本地的Apache安装,或者说是XAMPP。你说的普通Apache是什么意思?如果我问的不清楚,我道歉。你有什么特别的问题需要我进一步解释吗?正如奥拉夫所说,这个问题有两个方面。一句话很难回答。请考虑按照奥拉夫的建议把它拆开,同时一块一块地处理。在一个答案中处理所有这些问题对我们来说要求很高。掌握这一点的最快方法是阅读大量的文档并在测试环境中进行实验。文件都有,写得很好,一切都在那里。从顶部开始阅读列表中的每个文档。如果有不清楚的地方,Apache用户电子邮件列表也可以提供很好的支持。对于测试,我只使用我的站点的一个子域,该子域仅用于测试它,在它自己的
VirtualHost
中。你只需要一台Apache服务器就可以使用Apache服务器:)这真的很简单,只需几天的学习。测试可以通过本地Apache安装轻松完成。添加PHP来查看环境,但大多数情况下,一个普通的Apache就足够了。在研究了这一点之后,我必须承认,我甚至不理解您想要什么。我建议把它分成小块,一步一步地解决你的问题。我有一个本地的Apache安装,或者说是XAMPP。你说的普通Apache是什么意思?如果我问的不清楚,我道歉。你有什么特别的问题需要我进一步解释吗?正如奥拉夫所说,这个问题有两个方面。一句话很难回答。恳求