.HTACCESS 正在创建不必要的 301 重定向链 - 如何删除?

.HTACCESS 正在创建不必要的 301 重定向链 - 如何删除?

我的堆栈:

  • 阿帕奇/2.4.41

背景信息:

我最近为客户推出了一个新网站。在重新设计过程中,我们决定:

  • 切换到全站 HTTPS
  • 从 URL 中删除 .php 扩展名
  • 切换到 CMS

旧 URL 示例:
http://www.example.com/courses/acme-course.php

新 URL 示例:
https://www.example.com/courses/acme-course

我的问题:

当用户导航到其中一个旧 URL 时,会发生不必要的额外 301 重定向。

我不明白为什么要创建额外的 301 重定向,而不是使用单个 301 重定向将用户直接发送到正确的目标 URL。

有趣的观察:

当我使用带有 HTTPS 而不是 HTTP 的旧 URL 时,不会发生不必要的额外 301 重定向。

例子:
https://www.example.com/courses/acme-course.php _

使用上述 URL 将正确地执行单个 301 重定向到正确的目标 URL:https://www.example.com/courses/acme-course

以下是 301 重定向链的示例:

原始请求 URL:

http://www.example.com/courses/acme-course.php

第一次 301 重定向(不必要):

从:

http://www.example.com/courses/acme-course.php

到:

https://www.example.com/index.php?url=courses/acme-course.php

第二次 301 重定向(正确的最终目标网址):

从:

https://www.example.com/index.php?url=courses/acme-course.php

到:

https://www.example.com/courses/acme-course

我的.htaccess 代码:

# (1) General Settings
<IfModule mod_rewrite.c>
    Options +FollowSymLinks
    RewriteEngine On
</IfModule>

# (2) Force WWW
<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} !=off
    RewriteCond %{HTTP_HOST} !^www\. [NC]
    RewriteCond %{SERVER_ADDR} !=127.0.0.1
    RewriteCond %{SERVER_ADDR} !=::1
    RewriteRule ^ %{ENV:PROTO}://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</IfModule>

# (3) Force HTTPS
<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} !=on
    RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
</IfModule>

# (4) URL Routing for CMS
<IfModule mod_rewrite.c>

    RewriteCond %{HTTPS} =on
    RewriteRule ^ - [env=proto:https]
    RewriteCond %{HTTPS} !=on
    RewriteRule ^ - [env=proto:http]

    ## Check if file/directory exists
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d

    ## Route all other URLs to index.php/URL
    RewriteRule ^(.*)$ index.php?url=$1 [PT,L,QSA]
</IfModule>

答案1

你有两个主要问题....

  1. 文件中的指令顺序错误。需要删除.htaccessHTTP 到 HTTPS 和规范重定向www您的前端控制器将 URL 路由到您的 CMS。因此,错误的外部重定向会/index.php?url=courses/acme-course.php暴露您的内部 CMS URL 结构。
  1. 删除.php实际上不是由您的.htaccess指令执行的?!我认为这一定是由您的应用程序/CMS 逻辑执行的?因此,这将总是导致第二次重定向(因为.htaccess在同一 URL 路径上重定向到 HTTPS)。您需要在文件顶部执行类似下面的操作.htaccess来删除.php扩展名。

    RewriteRule (.+)\.php$ https://www.example.com/$1 [R=301,L]
    

更新:如果我重新排序规则/条件,我的选项 +FollowSymlinks 的位置是否保持不变?

这没什么关系在哪里指令Options发生。但是,将其放在顶部附近是合乎逻辑的(从可读性的角度来看)。(Apache 指令不一定按照它们在配置文件中出现的顺序执行,因为每个模块都独立工作。)

假设您正在手动编码.htaccess文件,那么它可以被整理......

  1. 不需要(多个)<IfModule mod_rewrite.c>包装器。mod_rewrite 是可选的吗?您的网站是否要移植到未启用 mod_rewrite 的多个服务器?

  2. 无需多个RewriteEngine指令。最后的例如胜利并控制整个文件。

    多个<IfModule>RewriteEngine是典型的通过代码自动编辑和/或设计为在多个服务器上不经编辑即可运行的系统。

因此,您的.htaccess文件应该按以下顺序重写:

Options +FollowSymlinks

# Enable the rewrite engine...   
RewriteEngine On

# ----------------------------------------------------------------------
# | Forcing `https://`                                                       |
# ----------------------------------------------------------------------

# Redirect to HTTPS on the "same host" (requirement for HSTS)
RewriteCond %{HTTPS} !=on
RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]


# ----------------------------------------------------------------------
# | Forcing `www`                                                          |
# ----------------------------------------------------------------------

RewriteCond %{HTTP_HOST} !^www\.
RewriteCond %{SERVER_ADDR} !=127.0.0.1
RewriteCond %{SERVER_ADDR} !=::1
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# ----------------------------------------------------------------------
# | URL Routing for CMS                                              |
# ----------------------------------------------------------------------

# (3)
RewriteCond %{HTTPS} =on
RewriteRule ^ - [env=proto:https]
RewriteCond %{HTTPS} !=on
RewriteRule ^ - [env=proto:http]
   
# (4) - Check if physical file exists
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d  

# (5) - Rewrite all other URLs to index.php/URL
RewriteRule (.*) index.php?url=$1 [L,QSA]

补充笔记:

  • 环境PROTO变量包含所请求的任何协议。按照重定向的顺序,现在将始终是 HTTPS。这个变量的根本原因是,如果访问的是 HTTP,CMS 可以重定向到 HTTP;如果访问的是 HTTPS,CMS 可以重定向到 HTTPS。如果您强制使用 HTTPS,那么它实际上并不适用。(尽管您的应用程序可能仍会使用此环境变量。)

  • 您很少应该NC在否定条件下使用该标志。因此,我将其从条件中删除!^www\.。您希望它在主机不以www.- 全部小写开头时重定向。使用该NC标志将无法重定向WwW.- 尽管这种情况无论如何都非常罕见。

  • 我已经删除了 www 规范重定向上不必要的 HTTPS 检查。

  • PT最后的标志在RewriteRule中不是必需的.htaccess.htaccess这是默认行为(传递)。

  • 您需要在测试之前清除浏览器缓存,因为错误的 301 重定向很可能已被浏览器缓存。因此,使用 302(临时)重定向进行测试是个好主意。

相关内容