如何向 RewriteRule 添加条件以排除子目录中不存在的文件?
How can I add a condition to RewriteRule that would exclude files that do not exist in a subdirectory?
如果页面不存在,我希望排除规则被调用。在我现有的 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 ^([^.]+)/$ .php [NC,L]
# 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
(或 </code> 反向引用)并构造绝对文件名。例如:</p>
<pre><code># 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 to the following question on ServerFault which goes into more detail about what REQUEST_FILENAME
is actually set to. https://serverfault.com/questions/989333/using-apache-rewrite-rules-in-htaccess-to-remove-html-causing-a-500-error
如果页面不存在,我希望排除规则被调用。在我现有的 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 ^([^.]+)/$ .php [NC,L]
# 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
(或 </code> 反向引用)并构造绝对文件名。例如:</p>
<pre><code># 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 to the following question on ServerFault which goes into more detail about what REQUEST_FILENAME
is actually set to. https://serverfault.com/questions/989333/using-apache-rewrite-rules-in-htaccess-to-remove-html-causing-a-500-error