.htaccess:重定向删除文件扩展名,除非是查询字符串的一部分

.htaccess: Redirect removing file extensions unless part of a query string

这里的许多答案都很接近,但 none 是完整的。

我希望 .htaccess 重定向并删除 php/html 扩展名和尾部斜杠,以便所有文件、目录和引导程序看起来都一样。问题是 URL 可能包含也可能不包含带有外部 URL link 的查询字符串,因此不应更改。

  1. 场景 1:从简单的 URL 中删除“.php”。
    • 这个:examle.com/file.PHP
    • 变成:examle.com/file
  2. 场景 2:从 URL 中删除“.php”,但不从查询中删除。
    • 这个:examle.com/file.PHP?link=anothersite.com/somefile.PHP
    • 变成:examle.com/file?link=anothersite.com/somefile.PHP

我有适用于一种或另一种情况的重写条件,但找不到同时适用于这两种情况的单一解决方案。

此条件适用于场景 1,但在场景 2 中失败,因为它还删除了查询字符串中 link 的扩展名。

RewriteCond %{THE_REQUEST} \/(.+)\.php

这(带有 \?)在场景 2 中有效,但仅在存在查询(问号)时有效,因此在场景 1 中失败。

RewriteCond %{THE_REQUEST} \/(.+)\.php\?

解决方案是一个正则表达式,它查看整个字符串,除非有问号。或者可能以某种方式解析任何问号处的字符串。我试过在问号处放置一个 "zero or one" 限定符,但它导致了重定向循环。

完成的代码看起来与此类似。

# Remove extensions shown in address bar
RewriteCond %{THE_REQUEST} "\/(.+)\.(php|jar|html|shtml|htm) [NC]
RewriteRule ^ /%1 [L,R=301]

# Remove trailing slashes
RewriteRule ^(.*)/$ / [R=301,L]

# Display php file if it exist 
rewriteCond %{REQUEST_FILENAME}.php -f
rewriteRule ^(.+)$ .php [L,QSA]

您可以使用此重定向规则使其适用于两个网址:

RewriteCond %{THE_REQUEST} \s/+([^?]+?)\.php[\s?] [NC]
RewriteRule ^ /%1 [R=302,NE,L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/$ / [NE,R=302,L]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)/?$ .php [L]

我已经为任何遇到与干净漂亮的 URL 相关的类似问题的人提供了这个最终代码。

下面的代码应该:

  1. 删除尾随垃圾(斜杠、问号、点等...)
  2. 隐藏不需要的扩展和索引
  3. 显示相关index.php / filename.php

感谢 anubhava 提供所需的解决方案。

RewriteEngine On
Options -Multiviews -Indexes +FollowSymLinks   
RewriteBase /
DirectorySlash Off

# Remove trailing question marks.
RewriteCond %{THE_REQUEST} \?[\s?] [NC]
RewriteRule ^(.*)$ /? [R,L]

# Remove unwanted extensions, dots, "index", punctuation, trailing slash
#   First condition group removed from anywhere in the path.
#   Second condition group only removed from the end of the path.
#   The rule will not alter text in the query. 
RewriteCond %{THE_REQUEST} \s/+([^?]+?)\.(php|jar|html|shtml|htm)([^\s]*?)[\s?] [NC,OR]
RewriteCond %{THE_REQUEST} \s/+([^?]+?)(\/index|\/|\.|,|\!])[\s?] [NC]
RewriteRule ^ /%1%3 [R,NE,L]

# If path points to a directory containing an index.php, use it
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME}/index.php -f
RewriteRule ^(.+)$ /index.php [L]

# ElseIf path/filename points to a php file, use it
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.+?)/?$ .php [L]

################################################################
# Below here is only needed if you want a bootstrap
# Without this, files will display or 404 as normal.
################################################################

# If none of the above conditions are met, 
# and the request is not an actual file (.jpg, .svg, etc.),
# display the bootstrap file making the path
# a query string for the bootstrap to parse.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?strappath= [QSA,L]

谢谢,如果有错误或漏洞,请告诉我。