如何在不破壞源文件的相對路徑載入的情況下重寫規則?
我在伺服器上有一個醜陋的文件系統路徑:
example.com/a/b/c/d/e/f/main.html
. 為簡單起見,我將example.com/httpdocs/main.html
在這個問題的正文中使用。我希望使用者看到的是
example.com/easy-to-remember
. 我將example.com/abc
在這個問題中使用。由於問題範圍之外的原因,我想只使用
.htaccess
文件而不是 php-routing。讓我們從有效的案例開始:
RewriteEngine On # Rewrite abc/ directory for loading of source material # Rewrite only if there is no actual file or directory that matches this request # This can especially be useful for loading resources # because then the full paths won't be redirected if they are correct. # Note that RewriteRule never sees leading slashes RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^abc/(.*)$ httpdocs/$1 [NC,L]
這樣,使用者可以打開
example.com/abc/main.html
(表達路徑)並顯示內部儲存在example.com/httpdocs/main.html
(醜陋路徑)的頁面。使用者永遠看不到內部路徑;url 保留/abc/main.html
在他們的瀏覽器中。到目前為止,一切都按預期工作。在相對路徑中指定的 CSS 源文件
main.html
仍然可以正確載入。但也許
main.html
是一個非常無用的名字。我寧願有example.com/abc
一個連結,而不是example.com/abc/main.html
. 這將更具表現力,並且允許在不更改連結的情況下對文件副檔名進行內部更改。# Rewrite abc without trailing slash to main.html RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^abc$ httpdocs/main.html # PROBLEM: This turns the current url into "example.com/abc", so "./libs" # is now looked for in "example.com/libs" instead of "example.com/httpdocs/libs"
此規則仍然適用於載入
main.html
而不在 url 中向使用者顯示該名稱。但是現在錯誤地解析了相對路徑。
/httpdocs/main.html
依靠/httpdocs/libs/source.css
. 在第一種情況下,我們訪問/abc/main.html
的地方,源是從中載入的/abc/libs/source.css
,這些載入被重定向到,/httpdocs/libs/source.css
所以一切正常。在我們訪問/abc
的第二種情況下,css 是從載入的/libs/source.css
,省略了/httpdocs
目錄 - 這會導致 404,因此頁面現在不再正確呈現(以這種方式訪問時)。顯而易見的解決方案是保留第一種情況,如果我真的不想向
main.html
使用者顯示名稱,我還可以添加一個重定向/abc/expressive-name
到/abc/main.html
(或直接到/httpdocs/main.html
)的規則。但我很好奇是否有辦法在不向 url 添加第二個深度級別(另一個斜線)的情況下實現我想要做的事情。
我想保持源的載入是相對的,這樣如果我不得不將整個文件系統移動到另一個子域左右,我可以將整個內容複製過來。如果沒有這種限制,我可以簡單地將所有負載設為絕對負載。
如您所見,您必須將主文件的 URL 保持在同一級別,以使相關連結正常工作。一種簡單的方法是使用 URL
/abc/
而不是/abc
.不同之處在於瀏覽器將其視為目前目錄或基本 URL。基本 URL 是在最後一個 . 之後刪除所有內容的 URL
/
。因此,/abc
基本 URL 是/
,而/abc/
基本 URL 是/abc
.所以你可以寫:
RewriteRule ^abc/$ httpdocs/main.html
或者你可以省略 URL 中的文件名,如果你提供它
#RewriteCond %{REQUEST_FILENAME} !-f #RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^abc(.*)$ httpdocs$1 DirectoryIndex main.html
RewriteCond 規則只是為了確保目標不是現有文件或目錄。如您所知,目標不存在,您可以省略規則。
如果您的主文件始終命名為 main.html,您可以
DirectoryIndex
只添加到根目錄(或共同祖先)。它會使 RewriteRules 更短,因為您不需要為目錄和主文件單獨的 RewriteRules。一個 get 請求
/abc
需要一個外部重定向到/abc/
,但是如果 apache 檢測到這/abc
是一個目錄,它會自動這樣做。外部重定向的一個有用工具是程序 wget,它可以顯示伺服器發送的重定向。