htaccess:防止 301 重定向将 / 附加到子文件夹的 URL 末尾

问题描述 投票: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
    • example
      (目录)
      • 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.com/example/
    返回
    /example/index.html
  • 的文件内容

但是这种情况也会发生,我想禁止这种情况:

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

您知道我必须在

.htaccess
文件中更改哪些内容吗?

apache .htaccess redirect mod-rewrite mod-dir
1个回答
1
投票

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
扩展名的规则。

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

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

# [NEW] 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]

# [NEW] Redirect to remove trailing slash on direct requests
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.+)/$ /$1 [R=301,L]

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

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

# Append ".html" if corresponding file exists
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.html -f
RewriteRule ^ %{REQUEST_URI}.html [L]

与您当前问题相关的新规则用

[NEW]
表示。

在测试之前,您需要清除浏览器缓存,因为附加尾部斜杠的 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.