Apache-2.2

檢查文件是否存在於子目錄中,否則將所有內容重定向到主控制器

  • May 17, 2020

我想在 Apache 下mod_rewrite.htaccess文件中執行以下操作:

  • 如果收到對任何文件或路徑的請求,例如foo.txtor foo/bar,請檢查該文件是否存在於public子目錄中,例如public/foo.txtor public/foo/bar。如果是這樣,只需顯示該文件。

  • 除此以外

    • 將所有內容重定向到主控制器index.php

我對解決方案的嘗試是這樣的:

<IfModule mod_rewrite.c>

   RewriteEngine On

   # Don't rewrite requests for files in the 'public' directory
   RewriteRule ^(public)($|/) - [L]

   # For all other files first check if they exist in 'public'
   RewriteCond %{DOCUMENT_ROOT}/public%{REQUEST_URI} -f
   RewriteRule ^ public%{REQUEST_URI} [L]

   # Let 'index.php' handle everything else
   RewriteRule . index.php [L]

</IfModule>

不幸的是,有一個重大缺陷:它在子目錄中不起作用,即當.htaccess和所有其他文件從 移動/到 時/sub/。理想情況下,它當然可以在任意子文件夾中工作。

有人可以幫忙嗎?如何修復.htaccess以消除該缺陷?

我有一個類似的問題,我想分發一個行為如您所描述的網路應用程序:特定目錄中有一堆靜態文件,可以像在網路應用程序根目錄上一樣訪問它們(即嘗試/images/pic.png獲取圖像in public/images/pic.png) ,其他所有內容都映射到控制器腳本。

我遇到的第一個問題是-finRewriteCond不適用於相對路徑 - 即如果“TestPattern”字元串可以解析為相對於指定條件的目錄的文件(使用.htaccess),-f仍將返回“不匹配” (1)。

因此,我們需要嘗試“理解”.htaccess文件所在的每個目錄前綴是什麼,並mod_rewrite實際上為我們解決了這個問題,並確保RewriteRule始終相對於每個目錄前綴.htaccess文件進行評估 - 但不幸的是它沒有不要以任何可以訪問的方式公開該資訊RewriteCond(他們真的應該讓我們擁有它)。

話雖這麼說,顯然你可以做一些奇怪的事情來強制“CondPattern”梳理出與輸入RewriteCond之間的關係- 閱讀這個問題的答案,了解你可以實現的所有奇怪的事情。%{REQUEST_URI}``RewriteRule

但是將這些技巧縮短到手頭的問題(-f匹配到相對於 .htaccess 的正確路徑,無論它可能在哪裡),我們得到了這個相當簡單的東西:

RewriteEngine On

RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2
RewriteCond %{DOCUMENT_ROOT}%1static/%2 -f
RewriteRule ^(.*)$  static/$1 [END]

RewriteRule . index.php [END,QSA]

解釋:

中的正則表達式RewriteCond非常有限,因為它不能解析變數和擷取的文本,但它可以使用\<number>語法使用對自身的反向引用。所以我們首先創建一個由以下組成的字元串:

  • 原始請求 URI
  • 我們不希望出現在 URL(::部分)中的硬編碼分隔符。
  • 將匹配的 URI 的本地(每個目錄)部分RewriteRule- 這是$1部分:RewriteCond可以查看目標RewriteRule(2)的擷取組,因此我們擷取整個輸入。

然後我們應用一個正則表達式來解釋該請求 URI 和RewriteRule輸入之間的關係 - 請求 URI 由兩部分組成(第一個和第二個擷取),其中第一個以 a 結尾,/第二個與出現在::delimiter -\2只是在同一個正則表達式中引用第二個擷取,並說它必須是相同的。

結果是我們將請求 URI 分解為兩個擷取組——第一個是mod_rewrite私有的本地每個目錄前綴,第二個是我們要檢查的目錄下的本地路徑。第二個條件用於引用這些在文件根(3)%<number>下建構絕對路徑的擷取。請注意,它擷取前綴 URI 的前導和尾隨斜杠。%1

最後,請注意我使用的是END標誌而不是L(last),因為它更快並且mod_rewrite立即存在。這允許我刪除與RewriteRule … - [L]which 存在的行,只是為了停止L實際上並沒有停止處理的行為:它只是回到開頭或使用新 URL 重寫規則。END簡單得多。

腳註:

  1. 實際上,相對路徑解析在某些條件下確實有效,如該問題的錯誤報告中所述。只是它沒有按預期工作,並且在大多數常見配置中根本無法工作。
  2. 這種看起來怪異的向後行為實際上非常簡單:Apache 總是首先解析 ,RewriteRule然後才檢查條件是否允許應用它。
  3. 順便說一句,如果您使用Alias或類似的方法將伺服器 URI 空間的一部分映射到不在文件根目錄下的其他位置,這將不起作用。請參閱文件CONTEXT_DOCUMENT_ROOT以了解如何解決此問題。

引用自:https://serverfault.com/questions/782951