.htaccess 没有 .php 也没有尾部斜杠

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

我有一个简单的网站,由 .php 文件组成,没有数据库。我使用 htaccess 来执行以下规则:

  • 强制https
  • 在开头强制 www
  • 删除 .php 扩展名(
    https://www.example.com/page.php
    ->
    https://www.example.com/page
  • 没有斜杠

最后一条规则,没有尾部斜杠,不起作用。相反,它会导致错误 404。这就是我要解决的问题。如果有人打开

https://www.example.com/page/
我希望它重定向到
https://www.example.com/page
而不是给 404.

这是我目前正在使用的相关

.htaccess
行。它基于 html5 样板 htaccess 添加了复制粘贴片段,因为我没有
.htaccess
知识。

ErrorDocument 404 /errors/404.php

Options -MultiViews

<IfModule mod_rewrite.c>

    # (1)
    RewriteEngine On

    # (2)
    Options +FollowSymlinks

</IfModule>

# to https

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTPS} !=on
  RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R] # to 301
</IfModule>

# force www at beginning

<IfModule mod_rewrite.c>

  RewriteEngine On

#     # (1)
  RewriteCond %{HTTPS} =on
  RewriteRule ^ - [E=PROTO:https]
  RewriteCond %{HTTPS} !=on
  RewriteRule ^ - [E=PROTO:http]

#     # (2)
#     # RewriteCond %{HTTPS} !=on

  RewriteCond %{HTTP_HOST} !^www\. [NC]
  RewriteCond %{SERVER_ADDR} !=127.0.0.1
  RewriteCond %{SERVER_ADDR} !=::1
  RewriteRule ^ %{ENV:PROTO}://www.%{HTTP_HOST}%{REQUEST_URI} [L,R] # <- for test, for prod use [L,R=301]

</IfModule>

# remove .php

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^([^\.]+)$ $1.php [NC,L]
</IfModule>

# remove trailing /

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_URI} (.*)/$
  RewriteRule ^(.*)/$ $1 [L,R] # <- for test, for prod use [L,R=301]
</IfModule>
apache .htaccess redirect mod-rewrite
1个回答
0
投票
# remove .php

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^([^\.]+)$ $1.php [NC,L]
</IfModule>

# remove trailing /

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_URI} (.*)/$
  RewriteRule ^(.*)/$ $1 [L,R] # <- for test, for prod use [L,R=301]
</IfModule>

这些规则的顺序是错误的。

/page/
的请求首先被重写为
/page/.php
(这自然会导致 404)before 你删除尾部斜杠(它不再有尾部斜杠,因为它以
.php
结尾)。

但是,删除尾部斜线的规则应该是检查请求是notadirectory,而不是not文件。第二个检查

REQUEST_URI
的条件是多余的。您还缺少 substitution 字符串上的斜杠前缀(并且没有定义
RewriteBase
),因此这会导致格式错误的重定向。

但是,您的规则可以大大简化。不需要

<IfModule>
包装器或多个
RewriteEngine On
指令,非 www 到 www 重定向不必要地保留方案(HTTP 或 HTTPS),当它始终是 HTTPS 时。

你的规则可以这样写得更简洁:

ErrorDocument 404 /errors/404.php

Options +FollowSymLinks -MultiViews

RewriteEngine On

# to https
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

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

# remove trailing /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ /$1 [R=301,L]

# remove .php (Actually, this "appends" .php, it doesn't "remove" anything)
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^.]+)$ $1.php [L]

我会质疑检查

SERVER_ADDR
的两个条件是否真的有必要,因为您在 HTTP 到 HTTPS 规则上没有类似的东西。

在正则表达式字符类中使用时无需反斜杠转义文字点。

您标记为“删除 .php”的规则实际上并未“删除”任何内容。它 appends

.php
扩展已经被删除的请求上的
.php
扩展。最好在尝试重写请求之前先测试相应的
.php
文件是否存在,而不是无条件地附加
.php
以希望该文件存在(这在某些情况下可能会导致意外错误,至少在
.php
请求上记录 404,而不是实际请求的 URL)。

如果请求 HTTP + 非 www,此规则块(根据您的原始规则块)也会导致两次重定向,因为您首先在同一主机上将 HTTP 重定向到 HTTPS。如果实施 HSTS,这实际上是一个要求,否则您可以通过颠倒前两个规则来避免这种双重重定向。 (但是,删除尾部斜杠的重定向也会导致编写的额外重定向。如果需要,可以更改此设置,但不会立即导致问题。)

NB:小心行尾注释(我已经删除了它们)。它们不受 Apache 支持。由于配置指令的解析方式,它们似乎可以正常工作,但如果您省略了任何可选参数,那么由于语法无效,您将收到 500 内部服务器错误。 (但是,是的,总是首先使用 302 - 临时 - 重定向进行测试。)

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