Kei*_*aCW 3 apache .htaccess mod-rewrite url-rewriting url-masking
类似的问题还有很多,但似乎没有一个完全适合我。
我正在从 WordPress 网站迁移到简单的静态网站。但是,目前禁止我public_html完全删除该文件夹中托管的 WordPress 网站,直到证明一切都可以与静态网站配合使用。
我将静态站点部署到我的文件夹中的子子文件夹中,public_html例如/subfolderA/newSiteFolder。
我已.htaccess使用以下命令更新了重定向到子子文件夹:
RewriteEngine on
RewriteCond %{REQUEST_URI} !newSiteFolder/
RewriteCond %{REQUEST_URI} !subfolderA/newSiteFolder/
RewriteRule (.*)$ /subfolderA/newSiteFolder/$1 [L]
Run Code Online (Sandbox Code Playgroud)
当通过按站点内的链接导航站点时,此功能可以正常工作并在地址栏中正确显示,但是当从外部链接导航到站点时,子文件夹将显示在地址栏中。
例如,如果从外部链接单击“关于”页面,则会显示为
https://example.com/subfolderA/newSiteFolder/about, 而不是https://example.com/about。
从外部链接单击时,如何屏蔽地址栏中的子文件夹名称?或者如何最好地改变我的重写规则来实现这一点?
我假设这about实际上是一个物理子目录/subfolderA/newSiteFolder/about,并且您打算从该目录提供DirectoryIndex文档(例如index.html)。
“问题”是,当您请求不带尾部斜杠的目录时,mod_dir 尝试通过 301(永久)重定向附加尾部斜杠来“修复”此问题,这会暴露已在内部重写的文件路径。
换句话说,当您请求/about(无尾部斜杠)时,您的 mod_rewrite 指令会在内部将请求重写为/subfolderA/newSiteFolder/about,但随后 mod_dir 启动并在外部将请求重定向到 ,/subfolderA/newSiteFolder/about/以附加尾部斜杠(这是必需的)。
规范 URL 包含尾部斜杠,这就是您在内部链接到的内容。因此,当映射到目录时,我们需要确保重写的 URL 上始终有一个尾部斜杠。在重写 URL之前,我们可以通过规范重定向来做到这一点。
Run Code Online (Sandbox Code Playgroud)RewriteCond %{REQUEST_URI} !newSiteFolder/ RewriteCond %{REQUEST_URI} !subfolderA/newSiteFolder/ RewriteRule (.*)$ /subfolderA/newSiteFolder/$1 [L]
第一个条件似乎是多余的。而且,此处使用的正则表达式未锚定,因此与请求的 URL 路径中任何位置的指定 URL 相匹配。
但是,我们不能只是将尾部斜杠附加到所有 URL,因为您可能拥有 CSS、JS 和图像等静态资源。对于任何静态文件,我们不能强制尾部斜杠,因此我们需要使用额外的方法来处理此问题规则。请尝试以下方法:
# Store the base directory in an environment variable
RewriteRule ^ - [E=BASEDIR:/subfolderA/newSiteFolder/]
# Rewrite the root (homepage) only
RewriteRule ^$ %{ENV:BASEDIR} [L]
# Finish early if we are already in the required base directory
RewriteCond %{ENV:BASEDIR}@%{REQUEST_URI} ^([^@]+)@\1
RewriteRule ^ - [L]
# If the request would map to a directory
# and it is missing a trailing slash
# then redirect to append the trailing slash
RewriteCond %{REQUEST_URI} !\.\w{2,4}$
RewriteCond %{DOCUMENT_ROOT}%{ENV:BASEDIR}$1 -d
RewriteRule ^(.+[^/])$ /$1/ [R=301,L]
# Rewrite everything to the base directory
RewriteRule (.+) %{ENV:BASEDIR}$1 [L]
Run Code Online (Sandbox Code Playgroud)
我选择使用第一条规则将“基本目录”(即/subfolderA/newSiteFolder/)存储在环境变量中BASEDIR,以保存整个文件中基本文件路径的重复。
Run Code Online (Sandbox Code Playgroud)RewriteCond %{ENV:BASEDIR}@%{REQUEST_URI} ^([^@]+)@\1
此条件检查请求的 URL(包括重写的 URL)是否已位于要重写的基目录内。该@字符只是一个不会出现在 URL 路径中的任意字符,它在正则表达式中没有任何特殊含义,除了分隔基本目录 ( BASEDIR) 和请求的 URL ( REQUEST_URI) 之外。\1是一个内部反向引用,用于检查请求的 URL 是否以基目录开头。
Run Code Online (Sandbox Code Playgroud)RewriteCond %{REQUEST_URI} !\.\w{2,4}$ RewriteCond %{DOCUMENT_ROOT}%{ENV:BASEDIR}$1 -d RewriteRule ^(.+[^/])$ /$1/ [R=301,L]
第一个条件排除任何以看起来像文件扩展名(即一个点后跟 2 到 4 个字符)结尾的请求,因此我们可以避免更昂贵的目录检查(如下)。这确实假设您没有以看起来像“文件扩展名”结尾的物理目录。
第二个条件测试所请求的 URL(例如/about)是否作为要重写的目录中的目录存在。
正则表达式^(.+[^/])$匹配(并捕获)任何尚未以斜杠结尾的 URL 路径。
注意:您需要确保在测试之前已清除浏览器缓存,因为之前附加尾部斜杠(也暴露了文件路径)的错误重定向是 301永久重定向,并且可能已被浏览器永久缓存。
对于之前
mydomain/subfolderA/newSiteFolder/about从外部链接导航到并将链接与子文件夹一起保存的用户,现在直接使用该链接,是否有办法修复该用户的 URL?
您可以阻止直接访问此“隐藏”子目录,并将用户重定向回“规范”URL,如下所示。这应该作为上面块中的第三条规则,位于“重写根...”规则之后。
# Redirect direct requests to the subdirectory back to root
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{ENV:BASEDIR}@%{REQUEST_URI} ^([^@]+)@\1(.*)
RewriteRule ^ /%2 [R=301,L]
Run Code Online (Sandbox Code Playgroud)
重要的是,检查环境变量的第一个条件REDIRECT_STATUS排除了后来重写的重写请求,因此该规则仅影响来自客户端的直接请求。
%2是对前面CondPattern中第二个捕获组的反向引用,即。URL路径中.BASEDIR
但是,如果用户之前被错误地重定向到子目录,则该重定向可能已被浏览器缓存,因此上述删除(撤消)子目录的重定向可能会导致这些用户不幸地发生重定向循环,直到他们清除为止他们的浏览器缓存。(此重定向循环可能会提示他们尝试清除浏览器缓存以解决问题;尽管也许不会。)
您也许可以重定向回包含无害查询字符串的 URL。这可能足以防止那些缓存了错误重定向的用户出现重定向循环(因为它不是其缓存中的 URL),但它确实会在 URL 上留下多余的查询字符串。例如,更改上面的RewriteRule指令:
:
RewriteRule ^ /%2?noredirect [R=301,L]
Run Code Online (Sandbox Code Playgroud)
noredirect只是任何查询字符串,以区别于缓存的 URL/重定向。
注意:首先使用 302(临时)重定向进行测试,以避免进一步/潜在的缓存问题。
RewriteEngine On
# Store the base directory in an environment variable
RewriteRule ^ - [E=BASEDIR:/subfolderA/newSiteFolder/]
# Rewrite the root (homepage) only
RewriteRule ^$ %{ENV:BASEDIR} [L]
# Redirect direct requests to the subdirectory back to root
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{ENV:BASEDIR}@%{REQUEST_URI} ^([^@]+)@\1(.*)
RewriteRule ^ /%2 [R=301,L]
# Finish early if we are already in the required base directory
RewriteCond %{ENV:BASEDIR}@%{REQUEST_URI} ^([^@]+)@\1
RewriteRule ^ - [L]
# If the request would map to a directory
# and it is missing a trailing slash
# then redirect to append the trailing slash
RewriteCond %{REQUEST_URI} !\.\w{2,4}$
RewriteCond %{DOCUMENT_ROOT}%{ENV:BASEDIR}$1 -d
RewriteRule ^(.+[^/])$ /$1/ [R=301,L]
# Rewrite everything to the base directory
RewriteRule (.+) %{ENV:BASEDIR}$1 [L]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
636 次 |
| 最近记录: |