Apache .htaccess RewriteRule 和 ErrorDocument
我有一個
.htaccess
文件:RewriteEngine On DirectorySlash Off RewriteCond %{REQUEST_URI} !(\.css|\.js|\.png|\.jpg|\.mp4|\.ttf|\.eot|\.woff)$ RewriteRule ^(.*)$ ?page=$1 [NC,L,QSA] ErrorDocument 404 /e404 ErrorDocument 403 /e404 ErrorDocument 500 /e500
還有一個 PHP 函式,用於檢查請求的 URI 是否存在。如果 URI 存在於數據庫中,則獲取內容並渲染頁面,如果不存在,則獲取 404 錯誤頁面內容並渲染頁面。(這裡一切正常)
問題是當我使用帶有文件
RewriteCond
部分內部副檔名的 URI 時.htaccess
,例如example.com/file.css
. 在這種情況下,頁面被重定向到example.com/e404
(這就是我想要的)。這裡的問題是:我不知道如何獲取重定向到之前使用的“錯誤 URI”
example.com/e404
,因為當載入錯誤頁面時,我在頁面內部有一個函式可以在數據庫中插入“錯誤 URI”。
*旁白:*您發布的指令會在任何預設的 Apache 安裝上創建一個重寫循環,所以也許您有其他指令或不同的配置,您沒有在您的問題中披露?無論如何,暫時忽略這一點,因為您似乎沒有遇到這樣的問題。
我不知道如何在重定向到之前使用錯誤的 URI
example.com/e404
…但是你需要在“重定向”*之前獲取這些資訊嗎?*在 PHP 中,您可以簡單地檢查
$_SERVER['REQUEST_URI']
超全域以獲取此資訊(導致 404 的 URL)。但是,請注意,這包含斜杠前綴和查詢字元串(如果有),page
否則您的 URL 參數不會包含它們。此外,為了澄清術語,這並不是嚴格意義上的“重定向”到
example.com/e404
. “重定向”意味著外部 HTTP 重定向。Apache 為錯誤文件發出一個內部子請求(類似於 URL 重寫,但不完全是)。您的程式碼的一個潛在問題是 404 響應是以一種相當迂迴的方式提供的:
- 如果
file.css
不存在,則 Apache 觸發內部子請求/e404
(這會觸發另一輪處理……) 2. 由於
/e404
不以所述文件副檔名之一結尾,因此將其進一步重寫為?page=e404
(大概index.php
?)。由於(不必要的)第二次重寫,其他伺服器變數,例如
REDIRECT_URL
和REDIRECT_QUERY_STRING
(也傳遞給 PHP$_SERVER
超全域變數)沒有按預期設置。通常,這些會被設置為“錯誤的 URI”(即觸發 404 的請求的 URL),但相反,它們包含錯誤文件本身的詳細資訊。您應該在 1 步中執行上述操作,並避免第二次重寫。例如(假設
index.php
是處理請求的文件),錯誤文件應該設置為期望的最終結果:ErrorDocument 404 /index.php?page=e404
順便說一句,您不一定需要
e404
在 URL 中顯式傳遞 HTTP“錯誤狀態”(即 ),因為這在 PHP 的$_SERVER['REDIRECT_STATUS']
超全域中是可用的。RewriteRule ^(.*)$ ?page=$1 [NC,L,QSA]
我假設您正在重寫
index.php
(註冊的 DirectoryIndex)?而不是退回到讓 mod_dir 為 DirectoryIndex 發出額外的子請求,您應該明確並將您正在重寫的文件包含在替換中。例如:RewriteRule ^(.*)$ index.php?page=$1 [QSA,L]
(
NC
旗幟在這裡是多餘的。)我不知道如何在重定向到之前使用錯誤的 URI
example.com/e404
…退後一步再次解決您的初始查詢(作為學術練習)。您可以在 Apache 2.4.13+ 上執行此操作(儘管我認為您不需要這樣做)。在 Apache 2.4.13+ 上,您可以使用 Apache 表達式創建動態 ErrorDocument。
例如,要在錯誤文件本身的 URL 中顯式傳遞導致 404 錯誤的 URL 路徑,則可以執行以下操作:
ErrorDocument 404 /index.php?page=%{escape:%{REQUEST_URI}}&error=404
然後 URL 參數
page
包含 URL 路徑(其中包括斜杠前綴,與您的重寫不同,它不包括它)。一個額外的error
URL 參數發送 HTTP 狀態(儘管如上所述,這不是絕對必要的)。