有很多類似的問題,但似乎沒有一個完全適合我。
我正在從 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]
通過按站點內的鏈接導航站點時,這可以正常作業并在地址欄中正確顯示,但是從外部鏈接導航到站點時,子檔案夾會顯示在地址欄中。
例如,如果從外部鏈接單擊 about 頁面,它將顯示為
https://example.com/subfolderA/newSiteFolder/about,而不是https://example.com/about。
從外部鏈接單擊時,如何屏蔽地址欄中的子檔案夾名稱?或者如何最好地改變我的重寫規則來完成這個?
uj5u.com熱心網友回復:
我假設這about實際上是一個物理子目錄,/subfolderA/newSiteFolder/about并且您打算從該目錄提供DirectoryIndex檔案(例如。 )。index.html
“問題”是,當您請求一個沒有尾部斜杠的目錄時,mod_dir 試圖通過 301(永久)重定向附加一個尾部斜杠來“修復”這個問題,這會暴露已在內部重寫的檔案路徑。
換句話說,當您請求/about(沒有尾部斜杠)時,您的 mod_rewrite 指令在內部將請求重寫為/subfolderA/newSiteFolder/about,但隨后 mod_dir 啟動并在外部將請求重定向到/subfolderA/newSiteFolder/about/以附加尾??部斜杠(這是必需的)。
規范 URL 包含尾部斜杠,這就是您在內部鏈接的內容。因此,當映射到目錄時,我們需要確保重寫后的 URL 始終有一個尾部斜杠。在重寫 URL之前,我們可以使用規范重定向來做到這一點。
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]
上述指令的解釋
I have chosen to store the "base directory" (ie. /subfolderA/newSiteFolder/) in an environment variable BASEDIR using the first rule to save repetition of the base file-path throughout the file.
RewriteCond %{ENV:BASEDIR}@%{REQUEST_URI} ^([^@] )@\1
This condition checks whether the requested URL (including the rewritten URL) is already inside the base directory being rewritten to. The @ character is just an arbitrary character that does not appear in the URL-path, it carries no special meaning in the regex, other than delimiting the base directory (BASEDIR) from the requested URL (REQUEST_URI). \1 is an internal backreference to check whether the requested URL starts with the base directory.
RewriteCond %{REQUEST_URI} !\.\w{2,4}$ RewriteCond %{DOCUMENT_ROOT}%{ENV:BASEDIR}$1 -d RewriteRule ^(. [^/])$ /$1/ [R=301,L]
The first condition excludes any request that ends in what looks-like a file extension (ie. a dot followed by between 2 and 4 characters), so we can avoid the more expensive directory check (that follows). This does assume that you don't have physical directories that end with what looks-like a "file extension".
The second condition tests whether the requested URL (eg. /about) exists as a directory inside the directory being rewritten to.
The regex ^(. [^/])$ matches (and captures) any URL-path that does not already end in a slash.
NB: You need to make sure you have cleared your browser cache before testing since the earlier erroneous redirect to append the trailing slash (that also exposed the file-path) was a 301 permanent redirect and will likely have been cached persistently by the browser.
Prevent direct access to the "hidden" subdirectory
Is there a way to also fix the URL for a user who was previously navigated to
mydomain/subfolderA/newSiteFolder/aboutfrom the external link and saved the link with the subfolders, and is now using that link directly?
You can prevent direct access to this "hidden" subdirectory and redirect the user back to the "canonical" URL with something like the following. This should go as the 3rd rule in the above block, after the "Rewrite the root ..." rule.
# Redirect direct requests to the subdirectory back to root
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{ENV:BASEDIR}@%{REQUEST_URI} ^([^@] )@\1(.*)
RewriteRule ^ /%2 [R=301,L]
Importantly, the first condition that checks against the REDIRECT_STATUS env var excludes rewritten requests by the later rewrite, so this rule only affects direct requests from the client.
%2 is a backreference to the 2nd captured group in the preceding CondPattern, ie. everything in the URL-path after the BASEDIR.
HOWEVER, if the user has previously been erroneously redirected to the subdirectory then this redirect will have likely been cached by the browser, so the above redirect to remove (undo) the subdirectory may result in a redirect-loop for these users unfortunately until they clear their browser cache. (This redirect-loop might prompt them to try and clear their browser cache to resolve the issue; although maybe not.)
You could perhaps redirect back to a URL that contains an innocuous query string. This might be enough to prevent a redirect loop for those users that have the erroneous redirect cached (since it's not a URL in their cache), but it does leave a superfluous query string hanging on the URL. For example, change the above RewriteRule directive:
:
RewriteRule ^ /%2?noredirect [R=301,L]
noredirect is just any query string to differentiate from the cached URL/redirect.
NB: Test first with a 302 (temporary) redirect to avoid further/potential caching issues.
Summary
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]
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/425153.html
