使用 .htaccess OpenLiteSpeed 服务器正确重定向 php id

Redirect php id Properly with .htaccess OpenLiteSpeed Server

我是 .htaccess 用法的新手,并试图通过在线资源学习,但是我写的规则相互抵消,我很难写出足够好的 .htaccess 文件,下面是我当前的 .htaccess 文件对于某些页面工作正常,例如删除扩展名和重写子域,请检查下面

## Flag for GoDaddy
Options +MultiViews

RewriteBase /

## Remove extensions
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !=f
RewriteRule ^([^\.]+)$ .php [NC,L]

## Redirect from extensions to non-extensions
RewriteCond %{THE_REQUEST} \s/+(.+?)\.php[\s?] [NC]
RewriteRule ^ /%1 [R=301,NE,L]

## Redirect Pages
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^post/([a-zA-Z0-9-/]+)$ /post.php?ps=
RewriteRule ^([a-zA-Z0-9-/]+)$ post-files.php?ps= [L,QSA]

## Server Only

## Redirect from www - non-www
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http:/// [R=301,L]


## SSL Redirect
## RewriteEngine On
## RewriteCond %{HTTPS} ≠On
## RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

## Create Error Pages
ErrorDocument 404 /errors/404.html
ErrorDocument 403 /errors/403.html
ErrorDocument 500 /errors/500.html

## Redirect non-existing pages to index.php
Options +SymLinksIfOwnerMatch
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

以上是我目前正在使用的 .htaccess,我是通过 youtube 上的教程得到它的 正如您在这条线上方看到的 RewriteRule ^post/([a-zA-Z0-9-/]+)$ /post.php?ps= 和它下方的线没有穿过 ps 但它们显示 404 页面

我希望结果是 domain.com/post-file-slug 以准确转到文件 domain.com/post-file.php?ps=post-slug-here 以获取规则 RewriteRule ^([a-zA-Z0-9-/]+)$ post-files.php?ps= [L,QSA]

domain.com/post/post-slug-here 精确到 domain.com/post.php?ps=post-slug-here 规则 RewriteRule ^post/([a-zA-Z0-9-/]+)$ /post.php?ps=

我已经为此工作了 2 天,希望尽快修复它。谢谢

## Flag for GoDaddy
Options +MultiViews

这在什么方面是“GoDaddy 的旗帜”?启用 MultiViews 将导致 ps URL 参数不会传递给 post.php 脚本。您需要确保禁用 MultiViews,以便以后的重写能够按预期工作。即

Options -MultiViews

MultiViews(mod_negotiation 的一部分)本质上支持无扩展 URLs。这将导致 /post/post-slug-here 请求被“重写”为 /post.php/post-slug-here 你的 mod_rewrite 指令被处理之前,所以它永远不会匹配并且永远不会重写请求以包含 ps URL 参数。

## Remove extensions
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !=f
RewriteRule ^([^\.]+)$ .php [NC,L]

## Redirect from extensions to non-extensions
RewriteCond %{THE_REQUEST} \s/+(.+?)\.php[\s?] [NC]
RewriteRule ^ /%1 [R=301,NE,L]

目前是 MultiViews 允许您的无扩展 URLs 工作。上面的第一个 conditionRewriteCond 指令)是不正确的。它应该是 !-f(不是文件),而不是 !=f(不等于“f”——总是正确的)。但是,这仍然是“错误的”,因为您需要在重写请求之前检查 .php 文件是否存在。如果您简单地重写所有未映射到文件的请求(这是您在这里尝试做的),那么以后对 post.phppost-files.phpindex.php 的重写将不会被处理如预期。

第二个条件中的正则表达式\s/+(.+?)\.php[\s?]并不严格正确,因为如果.php出现在查询字符串中,它将导致格式错误的重定向URL-path中省略了。例如。对 /foo?bar.php 的请求将导致重定向到 /foo?bar,而在这种情况下根本不应存在重定向。正则表达式只需要捕获 URL-path,因此将子模式 (.+?) 更改为 ([^?]+)

这两条规则也是反过来的。外部重定向应该是第一个。作为一般规则,外部重定向应始终在内部重写之前进行。

应该是这样的:

## Remove extensions
 
## Redirect to remove ".php" extension
RewriteCond %{THE_REQUEST} \s/+([^?]+?)\.php[\s?] [NC]
RewriteRule \.php$ /%1 [R=301,NE,L]

# Rewrite to append ".php" extension if corresponding ".php" file exists
RewriteCond %{DOCUMENT_ROOT}/.php -f
RewriteRule ^([^.]+)$ .php [L]

您应该已经链接到没有 .php 扩展名的文件。删除 .php 扩展名的重定向仅在更改现有 URL 结构时用于 SEO。

在正则表达式字符 class 中使用时,无需 backslash-escape 文字点。 NC 标志在这里是多余的。

## Redirect Pages
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^post/([a-zA-Z0-9-/]+)$ /post.php?ps=
RewriteRule ^([a-zA-Z0-9-/]+)$ post-files.php?ps= [L,QSA]

RewriteCond 指令仅适用于随后的第一个 RewriteRule 指令。所以,上面的第二条规则被无条件地处理——这是故意的吗?

其实那两个条件很可能是多余的。正则表达式似乎已经排除了实际文件,因为正则表达式排除了点。您是否需要能够直接访问文件系统目录?

class[a-zA-Z0-9-/]这个字很“迷惑”。最后一个连字符被视为文字连字符(大概是本意),但乍一看它可能看起来像一个范围说明符(如前面字符 class 中所用)。为避免在匹配字符 class 内的文字连字符时出现混淆,可以 backslash-escape 它,或者将其移至字符 class 中的第一个或最后一个字符。例如。 [a-zA-Z0-9/-].

您还缺少第一条规则中的 L 标志。 (您已将其包括在第二个中。)您还需要 QSA 标志吗? (即,您是否希望初始请求有额外的 URL 参数?)

修改了上面的“extension removal”规则,这个倒是无所谓,但是这些重写request到post.phppost-files.php的规则应该是上面的“扩展删除”规则。

## Redirect from www - non-www
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http:/// [R=301,L]

此规则不正确且位置错误。规范重定向(www 到 non-www 和 HTTP 到 HTTPS)通常应该高于其他规则。如上所述,重写前重定向。

但是这个规则也是完全不正确的。 </code> 是对 <code>RewriteRule 中第一个捕获的子模式的反向引用,因此 http:/// 自然会导致格式错误的重定向。第一个反向引用应该是 %1(到最后匹配的 CondPattern)以匹配请求的主机名。通常,您还应该在此处重定向到 HTTPS,而不是 HTTP。例如,规则应为:

:
RewriteRule (.*) https://%1/ [R=301,L]

围绕 RewriteRule 模式 ^$ 是多余的,因为默认情况下正则表达式是贪婪的。

## SSL Redirect
## RewriteEngine On
## RewriteCond %{HTTPS} ≠On
## RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

虽然注释掉了,但也是不正确的。它需要在其他重写之前进行。如果在 www 之后实现 HSTS ,它应该位于文件的顶部,如果不是,则重定向到 non-www(并最小化重定向的数量)。

前面的condition中的CondPattern应该是!on,而不是≠On(完全无效在两个方面... 无效,比较结果为 case-sensitive。HTTPS 将始终为小写。)

您还缺少 R=301L 标志。

RewriteRule模式中不需要捕获组,因为替换字符串中没有使用它. ^ 就足够了(而且效率更高)而不是 (.*)

## Create Error Pages
ErrorDocument 404 /errors/404.html
ErrorDocument 403 /errors/403.html
ErrorDocument 500 /errors/500.html

为了便于阅读,您应该在文件顶部定义您的自定义错误文档。 (从技术上讲,这并不重要。)

## Redirect non-existing pages to index.php
Options +SymLinksIfOwnerMatch
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

为了便于阅读,您应该在文件顶部一起定义 Options(与 -MultiViews)。例如:

Options -MultiViews -Indexex +SymLinksIfOwnerMatch

(禁用 Indexes - auto-generated 目录列表 - 是个好主意。)

您不需要重复 RewriteEngine 指令。 (只有该指令的最后一个实例执行任何操作。)将此规则放在文件顶部附近、第一个 mod_rewrite 指令之前是合乎逻辑的。 (尽管从技术上讲,该指令在文件中的位置实际上并不重要。)

旁白:您在内部重写时使用的前缀应该保持一致。在某些规则中,您包括斜杠前缀(例如 /post.php),而在某些规则中您省略了它(post-files.php)。您已经定义了 RewriteBase /(这里并不是严格要求的)- RewriteBase 仅适用于相对替换字符串(即省略斜杠前缀时)。


更新:

also i have file i want to exclude like 404.php in root directory from how do i exclude somefiles from the redirect. when i sent ajax to backend php file it redirected to homepage and failed to retrieve data.

要排除特定文件,您可以添加如下规则,规范重定向之后:

# Exclude "/404.php" from stripping the ".php" extension
RewriteRule ^404\.php$ - [L]

一般来说,一旦您为 .php 文件设置了无扩展名,您就应该无处不在。因此,不应有意外的重定向。重定向实际上仅用于 SEO。

关于您的 AJAX 请求,如果您正在发出 POST 请求,那么您可以简单地从进一步处理中排除所有 POST 请求。例如:

# Prevent further processing of POST requests to ".php" files
RewriteCond %{REQUEST_METHOD} POST [NC]
RewriteRule \.php$ - [L]

或者(或同时),如果您的 AJAX 请求正在设置自定义 HTTP 请求 header 那么您也可以检查它。


总结

综合以上几点,应该是这样的:

## Disable MultiViews and Indexes
Options -MultiViews -Indexes +SymLinksIfOwnerMatch

## Create Error Pages
ErrorDocument 404 /errors/404.html
ErrorDocument 403 /errors/403.html
ErrorDocument 500 /errors/500.html

RewriteEngine On

RewriteBase /

#### Canonical redirects

## SSL Redirect
## RewriteCond %{HTTPS} !on
## RewriteRule (.*) https://%{HTTP_HOST}/ [R=301,L]

## Redirect from www - non-www
## >>> CHANGE TO "HTTPS://"
RewriteCond %{HTTP_HOST} ^www\.(.+) [NC]
RewriteRule (.*) http://%1/ [R=301,L]

#### Rewrite Pages

RewriteRule ^post/([a-zA-Z0-9/-]+)$ post.php?ps= [QSA,L]
RewriteRule ^([a-zA-Z0-9/-]+)$ post-files.php?ps= [QSA,L]

#### Exceptions

## Exclude "/404.php" from stripping the ".php" extension
RewriteRule ^404\.php$ - [L]

## Prevent further processing of POST requests to ".php" files
RewriteCond %{REQUEST_METHOD} POST [NC]
RewriteRule \.php$ - [L]

#### Remove extensions

## Redirect to remove ".php" extension
RewriteCond %{THE_REQUEST} \s/+([^?]+)\.php[\s?] [NC]
RewriteRule \.php$ /%1 [R=301,NE,L]

## Rewrite to append ".php" extension if corresponding ".php" file exists
RewriteCond %{DOCUMENT_ROOT}/.php -f
RewriteRule ^([^.]+)$ .php [L]

## Redirect non-existing pages to index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]