如何向 RewriteRule 添加条件以排除子目录中不存在的文件?

Posted

技术标签:

【中文标题】如何向 RewriteRule 添加条件以排除子目录中不存在的文件?【英文标题】:How can I add a condition to RewriteRule that would exclude files that do not exist in a subdirectory? 【发布时间】:2021-11-22 16:35:51 【问题描述】:

如果页面不存在,我希望排除调用规则。在我现有的 htaccess 中,当用户从根目录访问不存在的页面时,此规则按预期工作。奇怪的是,如果用户试图访问一个不存在的有效页面的子目录,它就不起作用。

我的 htaccess 的当前行为:

example.com/valid-page/ -> example.com/valid-page/ (good)
example.com/valid-page -> example.com/valid-page/ (good)
example.com/valid-page/valid-page -> example.com/valid-page/valid-page/ (good)
example.com/does-not-exist -> example.com/does-not-exist (good)
example.com/valid-page/does-not-exist -> example.com/valid-page/does-not-exist/ (boo!)

对于上面的坏例子,期望的结果应该是不包含正斜杠:

example.com/valid-page/does-not-exist -> example.com/valid-page/does-not-exist

这是.htaccess:

# Redirects for errors
ErrorDocument 404 /error.php
ErrorDocument 403 /error.php

# Hides directory file listings
Options -Indexes

# Turn mod_rewrite on
RewriteEngine On
RewriteBase /

# Force slash at end of URL
RewriteCond %REQUEST_URI /+[^\.]+$
RewriteCond %REQUEST_FILENAME.php -f
RewriteRule ^(.+[^/])$ %REQUEST_URI/ [R=301,L]

# To externally redirect /dir/foo.php to /dir/foo
RewriteCond %THE_REQUEST ^[A-Z]3,\s([^.]+)\.php [NC]
RewriteRule ^ %1 [R,L]

# To internally forward /dir/foo to /dir/foo.php
RewriteCond %SCRIPT_FILENAME !-d
RewriteRule ^([^.]+)/$ $1.php [NC,L]

【问题讨论】:

【参考方案1】:
# Force slash at end of URL
RewriteCond %REQUEST_URI /+[^\.]+$
RewriteCond %REQUEST_FILENAME.php -f
RewriteRule ^(.+[^/])$ %REQUEST_URI/ [R=301,L]

您需要更改检查REQUEST_FILENAME 的第二个条件,因为当您请求/valid-page/does-not-exist 时,REQUEST_FILENAME.../valid-page,而不是您所期望的.../valid-page/does-not-exist

代替REQUEST_FILENAME,使用REQUEST_URI(或$1 反向引用)并构造绝对文件名。例如:

# Force slash at end of URL
RewriteCond %REQUEST_URI /+[^\.]+$
RewriteCond %DOCUMENT_ROOT%REQUEST_URI.php -f
RewriteRule ^(.+[^/])$ %REQUEST_URI/ [R=301,L]

您需要在测试前清除浏览器缓存,因为错误的 301(永久)重定向将被浏览器缓存。使用 302(临时)重定向进行测试以避免缓存问题。

现在,当您请求 /valid-page/does-not-exist 时,您正在检查 .../valid-page/does-not-exist.php 是否作为文件存在,而不是像以前一样存在 .../valid-page.php

请参阅my answer 以了解有关 ServerFault 的以下问题,该问题更详细地了解了 REQUEST_FILENAME 的实际设置。 https://serverfault.com/questions/989333/using-apache-rewrite-rules-in-htaccess-to-remove-html-causing-a-500-error

【讨论】:

以上是关于如何向 RewriteRule 添加条件以排除子目录中不存在的文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在magento 2中排除css以单独从主页加载?

RewriteRule 301重定向整个目录和子目录

如何向 Swift 数组添加扩展以有条件地追加?

从 RewriteRule 中排除文件夹/目录

.htaccess & WordPress:从 RewriteRule 中排除文件夹

向 .htaccess 添加注释