
我正在重寫從舊開發團隊收到的 Apache 2.4 配置。
我有大約 200 行類似的配置,我不明白我需要根據什麼原則更改此程式碼以將其從.htaccess
虛擬主機移至虛擬主機。
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteCond %{REQUEST_URI} !^/application-module/(.*)$
RewriteCond %{REQUEST_URI} !(.*)json$ [NC]
RewriteCond %{REQUEST_URI} !playground/local-loader/(.*)$ [NC]
RewriteRule ^(.*)$ /$1/ [R,L,NC]
當我將其移動到虛擬主機時,我的網站在我不明白的地方崩潰了。
答案1
這取決於<VirtualHost>
您將這些指令放置在容器中的位置。
如果您使用的是<Directory>
容器(即目錄上下文)和停用 .htaccess
完全覆蓋(否則.htaccess
將覆蓋<Directory>
容器!),那麼您幾乎可以按原樣複製指令(假設容器<Directory>
引用與檔案相同的目錄.htaccess
)。
但是,如果您將這些指令直接放入容器內<VirtualHost>
(在容器之外)<Directory>
),即。在一個虛擬主機上下文,那麼你需要做出一些改變。這是因為在請求映射到檔案系統之前指令會被提前處理。
在您發布的指令中,只需要進行兩處更改:
在一個虛擬主機上下文中,
REQUEST_FILENAME
伺服器變數尚未解析為檔案名稱。它與REQUEST_URI
(即請求的 URL)相同。因此,您的檔案系統檢查將始終失敗,而條件將始終成功!您要么需要使用前瞻。例如。%{LA-U:REQUEST_FILENAME}
,或者自己建構絕對檔名。例如。%{DOCUMENT_ROOT}%{REQUEST_URI}
。例如:RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
在一個虛擬主機context,匹配的 URL 路徑
RewriteRule
圖案是相對根的(以斜線開頭)。而 in.htaccess
它是相對於包含該檔案的目錄.htaccess
- 減去斜線前綴。因此,所編寫的規則將導致 URL 路徑開頭出現雙斜杠,應該像這樣重寫:RewriteRule ^/(.*)$ /$1/ [R,L]
(
NC
此處不需要該標誌。)或者(最好)不要在這裡使用反向引用,而是使用伺服器變數(這自然也
REQUEST_URI
可以工作)。.htaccess
例如:RewriteRule ^ %{REQUEST_URI}/ [R,L]
(在旁邊:這可能也應該是 301 永久重定向(即
R=301
)。按照目前的情況,這將預設為 302 暫時重定向。但只有在確認它按預期工作後才更改為 301(如果這是意圖)。
所以,總而言之,這將變成:
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteCond %{REQUEST_URI} !^/application-module/(.*)$
RewriteCond %{REQUEST_URI} !(.*)json$ [NC]
RewriteCond %{REQUEST_URI} !playground/local-loader/(.*)$ [NC]
RewriteRule ^/(.*)$ /$1/ [R,L]
在旁邊:
透過行動檔案系統檢查(相對而言),可以立即優化上面的內容昂貴的)到最後一個條件並移動狀態檢查請求是否尚未以RewriteRule
指令的斜線結尾。此外,(.*)
每個中的正規表示式子模式狀況不需要。因此,上面的程式碼可以更有效地重寫:
RewriteCond %{QUERY_STRING} ^$
RewriteCond %{REQUEST_URI} !^/application-module/
RewriteCond %{REQUEST_URI} !json$ [NC]
RewriteCond %{REQUEST_URI} !playground/local-loader/ [NC]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule !/$ %{REQUEST_URI}/ [R,L]
如果您排除包含(看起來像)檔案副檔名的請求,則可能可以完全刪除檔案系統檢查,但這可能取決於您的檔案結構。
這狀態該檢查!json$
看起來應該真正檢查.json
檔案副檔名,即。!\.json$
。 (這與我上面關於排除的評論相關全部具有「檔案副檔名」的請求。
首先狀態檢查查詢字串是否為空似乎有點奇怪(因為在 URL 路徑中附加斜線時是否有查詢字串並不重要),但我認為這一定是一個特定的要求?