htaccess:在子文件夹的 URL 末尾使用 / 禁用 301 重定向

问题描述 投票:0回答:1

我定义了这个htaccess-文件:

RewriteEngine On

# Disable http
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# Disable www.
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]

# /random run random.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^([^\.]+)$ $1.php [NC,L]

# Redirect /index.html in URL to /
RewriteRule (.*)index\.html$ /$1 [R=301,L]

# Redirect xxx.html in URL to nach xxx
RewriteCond %{THE_REQUEST} /([^.]+)\.html [NC]
RewriteRule ^ /%1 [NC,L,R]

RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^ %{REQUEST_URI}.html [NC,L]

我有这个文件夹结构:

    • index.html
    • about.html
    • 示例
      • index.html
      • x.html

效果很好

  • 主页是x.com
  • x.com/about 返回 /about.html 的文件内容
  • x.com/about.html 重定向至 x.com/about
  • x.com/example/x 返回 /example/x.html 的文件内容
  • x.cim/example/ 返回 /example/index.html 的文件内容

但这也发生了,我想禁止:

  • x.com/example 重定向到 x.com/example/
  • x.com/example 应该返回 /example/index.html 的文件内容

你知道我必须在 htaccess 中更改什么吗?

apache .htaccess http redirect
1个回答
0
投票

x.com/example
重定向至
x.com/example/

由于

/example
是一个物理目录,mod_dir “修复”URL 并在尾部斜杠后面附加 301(永久)重定向。尾部斜杠是 required 以便从该目录提供
DirectoryIndex
(即本例中的
index.html
)。

但是,我们可以使用

DirectorySlash Off
指令阻止 mod_dir 附加尾部斜杠。但是,我们必须发出内部重写以附加尾部斜杠,否则将无法提供
DirectoryIndex
文档(如上所述)。 (或者,我们可以直接重写索引文档。)

设置

DirectorySlash Off
时,我们还必须确保禁用目录列表(mod_autoindex),因为该目录中存在索引文档将不再阻止目录列表。

为了解决潜在的规范化问题,您现在需要向另一个方向“重定向”,以删除所请求 URL 上的任何尾部斜杠。例如。发送至

/example/
的请求现在需要重定向回
/example

此外,以下重写对应

.html
文件的规则并不严格正确:

RewriteCond %{REQUEST_FILENAME}.html -f
RewriteRule ^ %{REQUEST_URI}.html [NC,L]

条件(使用

REQUEST_FILENAME
)不一定测试您最终在替换(使用
REQUEST_URI
)中重写的相同URL。因此,在某些情况下(例如,当请求目录中不存在的文件时,该文件也恰好映射到
.html
文件),您可能会遇到重写循环(500 内部服务器错误)。请参阅以下关于 ServerFault 的问题/答案,其中更详细地介绍了这一点:https://serverfault.com/questions/989333/using-apache-rewrite-rules-in-htaccess-to-remove-html-causing-a -500-错误

这同样适用于之前附加

.php
扩展名的规则。

将以上几点综合起来,我们得到以下结论:

# Directory listing (mod_autoindex) must be disabled
Options -Indexes

# Prevent mod_dir appending the trailing slash
DirectorySlash Off

RewriteEngine On

# Disable http
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# Disable www.
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]

# Redirect /index.html in URL to /
RewriteRule (.*)index\.html$ /$1 [R=301,L]

# Redirect xxx.html in URL to just xxx
RewriteCond %{THE_REQUEST} /([^.?]+)\.html [NC]
RewriteRule ^ /%1 [R=301,L]

# Redirect to remove trailing slash
# (Can be unconditional if ALL URLs should not have a trailing slash)
RewriteRule (.+)/$ /$1 [R=301,L]

# /random run random.php
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^\.]+)$ $1.php [L]

# Internal rewrite to append trailing slash to directories
RewriteCond %{DOCUMENT_ROOT}/$1 -d
RewriteRule (.+) $1/ [L]


RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.html -f
RewriteRule ^ %{REQUEST_URI}.html [L]

在测试之前,您需要清除浏览器缓存,因为附加尾部斜杠的 301(永久)重定向将被缓存。使用 302(临时)重定向进行测试以避免潜在的缓存问题。

补充说明:

  • 在测试同一请求加上

    .php
    does 映射到文件之前,测试请求是否未映射到文件是没有意义的,这些是互斥的事件,特别是因为您的
    RewriteRule
    pattern 不包括点(因此排除带有文件扩展名的 URL),所以我删除了该 条件

  • 无需反斜杠转义

    RewriteCond
    TestString 中的文字点,因为这是一个“普通”字符串,而不是正则表达式。

  • 两个

    NC
    指令上不需要
    RewriteRule
    标志,因为正则表达式已经匹配 a-z 和 A-Z。

  • 我在内部重写之前对规范重定向进行了分组。

# Redirect xxx.html in URL to nach xxx RewriteCond %{THE_REQUEST} /([^.]+)\.html [NC] RewriteRule ^ /%1 [NC,L,R]

请注意,我还修改了此规则的

condition 中的正则表达式,以避免匹配潜在的查询字符串,否则 /foo.html?bar.html

 形式的请求将错误重定向。

注意:您目前没有针对

.php

 请求的相应规则。 (您可以在同一规则中处理两者。

© www.soinside.com 2019 - 2024. All rights reserved.