我目前有一个混乱的 Apache .htaccess 文件来(尝试)确保我网站上每个页面的规范 URL,并且该 URL 不反映底层技术或页面是文件还是目录。例如:
recipes/frigidaire.html
具有 example.com/recipes/frigidaire/ 的规范 URL; recipes/frigidaire.html、recipes/frigidaire.php 和 recipes/frigidaire/index.html(例如)的请求都重定向到规范 URL。recipes/index.php
具有 example.com/recipes/ 的规范 URL 和对 recipes/index.php、recipes/index.html 等的请求,所有重定向到规范 URL。这意味着,如果我稍后将
frigidaire.html
更改为frigidaire.php
,例如,URL不会更改。或者,如果我将一些子页面添加到frigidaire
,这样它就从一个文件变成一个目录,它的URL也不会改变。
任何对页面的请求,如果它还不是规范的 URL,将被重定向到规范的 URL。
具体来说,我确实不希望无论URL如何都显示正确的页面。我希望显示正确的页面 只有 对规范 URL 的请求;该页面可能的其他请求应重定向到规范 URL。
这是我的大多数域的顶级 .htaccess 文件中的示例。我已经大大减少了。涵盖的案例更多。例如,真实集或重写中的文件扩展名更多;并且完整的集合处理某些类型文件的内容处理问题。
#If the request is for an existing directory, we're done
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ - [L]
#Apache lets dynamic files accept slashes at the end
#redirect dynamic file endings to their "directory" equivalent
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)/index\.php/?$ {% page SELF -relative %}$1/ [R=301,L]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)\.php/?$ {% page SELF -relative %}$1/ [R=301,L]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)/index/?$ {% page SELF -relative %}$1/ [R=301,L]
#redirect known file endings to their "directory" equivalent
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)\.(au|bin|cpt|doc|dot|dvi|eps|exe|gif|html|jpe?g|manifest|php|pdf|png|ps|ps\.Z|ps\.z|ps\.gz|rss|rtf|rtf\.gz|shtml|sit|sit\.hqx|tar|tar\.gz|tar\.Z|txt|TXT|xhtml|zip.uu)$ {% page SELF -relative %}$1/ [R=301,L]
#need to put .Z on its own, or it takes precedence over ps.Z, etc.
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)\.(hqx|Z|zip)$ {% page SELF -relative %}$1/ [R=301,L]
#if it has no slash after it, add a slash and start over
#we should not have any .html, etc., at this point because we redirected them above
RewriteCond %{ENV:REDIRECT_STATUS} ^$
#if there is a query string, we can't do this, because the slash will be appended after the query string, not after the filepath
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{THE_REQUEST} ({% page SELF -relative %}[^\ ]+)
RewriteRule ^(.*[^/])$ %1/ [R=301,L,NE]
#Get the base path without the slash
RewriteRule ^(.*)/$ $1 [E=NEWCHECK:$1]
#If there is a .html file, use it
RewriteCond {% page SELF -fullpath %}%{ENV:NEWCHECK}.html -f
RewriteCond %{THE_REQUEST} ({% page SELF -relative %}[^\ ]+)/
RewriteRule ^(.*)/$ %1.html [L,NE]
#If there is an .xhtml file, use it
RewriteCond {% page SELF -fullpath %}%{ENV:NEWCHECK}.xhtml -f
RewriteRule ^(.*)/$ $1.xhtml [L]
#If there is a .php file, use it
RewriteCond {% page SELF -fullpath %}%{ENV:NEWCHECK}.php -f
RewriteRule ^(.*)/$ $1.php [L]
#If there is a .txt file, use it
RewriteCond {% page SELF -fullpath %}%{ENV:NEWCHECK}.txt -f
RewriteCond %{THE_REQUEST} ({% page SELF -relative %}[^\ ]+)/
RewriteRule ^(.*)/$ %1.txt [L,NE]
有很多similarquestions与solutions在那里,都像我一样使用重写规则。在不使用重写的情况下,有没有更简单的方法在 Apache 中执行此操作?这是一组漫长而曲折的重写,我一直认为应该为此设置一个简单的 .htaccess 设置。这似乎是一个足够普遍的要求。
我担心这种对每个请求的重写会给服务器带来不必要的负担。我也知道它非常复杂,并且仍然存在无法产生我想要的结果的边缘情况。
但是我找不到类似的东西
Options +FolderizeAllURLs +Redirect
我看到了使用MultiViews的建议。
Options +MultiViews
但这似乎无法处理重定向到规范 URL 的问题。它还似乎允许各种奇怪的 URL。例如,
recipes/News/2023.php
将与以下请求一起显示:
随着错误的产生,允许指向这个特定页面的非常错误的 URL 永无止境地扩展,这与我正在寻找的几乎完全相反:
是否有更可靠的方法和/或服务器密集程度较低的方法?