如果 index.html 不存在于没有尾部斜杠的目录中,则服务 index.php
Serve index.php if index.html is not present in directory without a trailing slash
我有一个带有子目录的 HTML 网站。
我需要的是:
- 访问没有尾部斜杠的子目录,即。 (
example.com/blog
) 不是 (example.com/blog/
)
- 如果某个子目录下没有
index.html
,它应该寻找index.php
。
/blog/
页面是一个带有自己 .htaccess
.
的 WordPress 页面
这是我当前的根 .htaccess
:
RewriteEngine on
ErrorDocument 404 /error/error404.html
DirectorySlash Off
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}/index.html -f
RewriteRule ^(.*)$ //index.html [L]
WordPress .htaccess
在 /blog/.htaccess
:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /blog/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /blog/index.php [L]
</IfModule>
(由 Wordpress 自动生成)
至于现在,html 文件可以在某些子目录下访问,但不能使用 index.php。我该怎么办?
DirectoryIndex
文档列出了在请求目录时尝试提供的文件。你不需要mod_rewrite。
但是,要在设置 DirectorySlash Off
时使用 DirectoryIndex
,您需要手动将尾部附加到具有内部重写的目录,否则,即使该目录包含,也会触发 403一份 DirectoryIndex
文件。 (正是出于这个原因,需要禁用 mod_autoindex 以防止意外泄露信息 - DirectoryIndex
文档的存在不足以防止 DirectorySlash Off
时自动生成的目录列表已设置。)
例如:
# Disable directory listings (mod_autoindex)
Options -Indexes
ErrorDocument 404 /error/error404.html
# Look for index.html then index.php in the directory being requested
DirectoryIndex index.html index.php
# Prevent mod_dir appending the trailing slash
DirectorySlash Off
RewriteEngine On
# If request a directory without a trailing slash then rewrite to append it
# This allows DirectoryIndex to work as intended
# - exclude the document root
RewriteCond !/$
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule (.+) / [L]
确保清除浏览器缓存。 mod_dir 发出 301(永久)重定向以附加尾部斜线。
更新#1:
/blog/
page is a WordPress page with its own .htaccess
.
问题在于,当在子目录中启用重写引擎时,它会完全覆盖父配置中的 mod_rewrite 指令,因此不会附加斜线,也不会触发目录索引( mod_rewrite 指令由于缺少斜线而未被处理)。 (这感觉有点先有鸡还是先有蛋。)
我成功解决这个问题的唯一方法是将 WordPress 指令移动到父配置中(进行必要的更改)并完全删除 /blog/.htaccess
。
例如,在上述指令之后附加以下修改后的 WordPress 指令:
# WordPress in "/blog" subdirectory
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteRule ^blog/index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^blog/. /blog/index.php [L]
更新#2:
have URL with trailing slash to redirect to URL without trailing slash? like for example, if I visit /about/
it should redirect to /about
?
是的,我们可以做到。由于我们要从 everything 中删除尾部斜杠,包括目录,这基本上是无条件的。唯一需要注意的是,删除尾部斜杠的规则必须仅适用于来自客户端的直接请求,而不适用于后来重写的重写请求,后者将尾部斜杠附加到目录,否则会导致重定向循环。
旁白: 你显然需要确保你所有的内部链接都不包含尾部斜杠,否则,用户将体验到外部重定向(对 SEO 和你的服务器不利).
我们可以通过检查 REDIRECT_STATUS
环境变量来做到这一点,该变量在初始请求中为 empty,并设置为 200
(如200 OK 状态)在第一次成功重写后(将尾部斜杠附加到目录)。
例如,以下内容应紧跟在 RewriteEngine
指令之后,现有重写之前:
# Redirect direct requests to remove trailing slash from all URLs
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.+)/$ / [R=302,L]
首先使用 302(临时)重定向进行测试,并在确认其按预期工作后更改为 301(永久)重定向。这是为了避免潜在的缓存问题。
总结
所有指令都已到位:
# Disable directory listings (mod_autoindex)
Options -Indexes
ErrorDocument 404 /error/error404.html
# Look for index.html then index.php in the directory being requested
DirectoryIndex index.html index.php
# Prevent mod_dir appending the trailing slash
DirectorySlash Off
RewriteEngine On
# Redirect direct requests to remove trailing slash from all URLs
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.+)/$ / [R=301,L]
# If request a directory without a trailing slash then rewrite to append it
# - This allows DirectoryIndex to work as intended
# - Exclude the document root
RewriteCond !/$
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule (.+) / [L]
# WordPress in "/blog" subdirectory
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteRule ^blog/index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^blog/. /blog/index.php [L]
我有一个带有子目录的 HTML 网站。
我需要的是:
- 访问没有尾部斜杠的子目录,即。 (
example.com/blog
) 不是 (example.com/blog/
) - 如果某个子目录下没有
index.html
,它应该寻找index.php
。
/blog/
页面是一个带有自己 .htaccess
.
这是我当前的根 .htaccess
:
RewriteEngine on
ErrorDocument 404 /error/error404.html
DirectorySlash Off
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}/index.html -f
RewriteRule ^(.*)$ //index.html [L]
WordPress .htaccess
在 /blog/.htaccess
:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /blog/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /blog/index.php [L]
</IfModule>
(由 Wordpress 自动生成)
至于现在,html 文件可以在某些子目录下访问,但不能使用 index.php。我该怎么办?
DirectoryIndex
文档列出了在请求目录时尝试提供的文件。你不需要mod_rewrite。
但是,要在设置 DirectorySlash Off
时使用 DirectoryIndex
,您需要手动将尾部附加到具有内部重写的目录,否则,即使该目录包含,也会触发 403一份 DirectoryIndex
文件。 (正是出于这个原因,需要禁用 mod_autoindex 以防止意外泄露信息 - DirectoryIndex
文档的存在不足以防止 DirectorySlash Off
时自动生成的目录列表已设置。)
例如:
# Disable directory listings (mod_autoindex)
Options -Indexes
ErrorDocument 404 /error/error404.html
# Look for index.html then index.php in the directory being requested
DirectoryIndex index.html index.php
# Prevent mod_dir appending the trailing slash
DirectorySlash Off
RewriteEngine On
# If request a directory without a trailing slash then rewrite to append it
# This allows DirectoryIndex to work as intended
# - exclude the document root
RewriteCond !/$
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule (.+) / [L]
确保清除浏览器缓存。 mod_dir 发出 301(永久)重定向以附加尾部斜线。
更新#1:
/blog/
page is a WordPress page with its own.htaccess
.
问题在于,当在子目录中启用重写引擎时,它会完全覆盖父配置中的 mod_rewrite 指令,因此不会附加斜线,也不会触发目录索引( mod_rewrite 指令由于缺少斜线而未被处理)。 (这感觉有点先有鸡还是先有蛋。)
我成功解决这个问题的唯一方法是将 WordPress 指令移动到父配置中(进行必要的更改)并完全删除 /blog/.htaccess
。
例如,在上述指令之后附加以下修改后的 WordPress 指令:
# WordPress in "/blog" subdirectory
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteRule ^blog/index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^blog/. /blog/index.php [L]
更新#2:
have URL with trailing slash to redirect to URL without trailing slash? like for example, if I visit
/about/
it should redirect to/about
?
是的,我们可以做到。由于我们要从 everything 中删除尾部斜杠,包括目录,这基本上是无条件的。唯一需要注意的是,删除尾部斜杠的规则必须仅适用于来自客户端的直接请求,而不适用于后来重写的重写请求,后者将尾部斜杠附加到目录,否则会导致重定向循环。
旁白: 你显然需要确保你所有的内部链接都不包含尾部斜杠,否则,用户将体验到外部重定向(对 SEO 和你的服务器不利).
我们可以通过检查 REDIRECT_STATUS
环境变量来做到这一点,该变量在初始请求中为 empty,并设置为 200
(如200 OK 状态)在第一次成功重写后(将尾部斜杠附加到目录)。
例如,以下内容应紧跟在 RewriteEngine
指令之后,现有重写之前:
# Redirect direct requests to remove trailing slash from all URLs
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.+)/$ / [R=302,L]
首先使用 302(临时)重定向进行测试,并在确认其按预期工作后更改为 301(永久)重定向。这是为了避免潜在的缓存问题。
总结
所有指令都已到位:
# Disable directory listings (mod_autoindex)
Options -Indexes
ErrorDocument 404 /error/error404.html
# Look for index.html then index.php in the directory being requested
DirectoryIndex index.html index.php
# Prevent mod_dir appending the trailing slash
DirectorySlash Off
RewriteEngine On
# Redirect direct requests to remove trailing slash from all URLs
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.+)/$ / [R=301,L]
# If request a directory without a trailing slash then rewrite to append it
# - This allows DirectoryIndex to work as intended
# - Exclude the document root
RewriteCond !/$
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule (.+) / [L]
# WordPress in "/blog" subdirectory
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteRule ^blog/index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^blog/. /blog/index.php [L]