Virtualhost

為什麼這個 -f 標誌返回 true?

  • May 28, 2019

我最近設置了一個重寫來盡可能地提供.webp文件來代替.jpg文件。它似乎工作正常,直到今天我們注意到一個新上傳的.jpg圖像正在返回,404即使圖像存在。我做了一些檢查,發現伺服器正在將.jpgURL 重寫為.webp,然後得到 a404因為.webp尚未創建。

然後,我將規則從 vhost_ssl.conf 移至 .htaccess 並進行了大量修改,直到找到可行的方法,然後將該解決方案移回 vhost_ssl.conf。但我還是不明白為什麼原來的重寫有時會失敗。任何人都可以回顧並闡明這個主題嗎?

原文改寫:

RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{DOCUMENT_ROOT}/%1.webp -f
RewriteRule (.+)\.(?:jpe?g|png)$ $1.webp [NC,T=image/webp,E=webp,L]

最後重寫:

RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_URI} (.+)\.(?:jpe?g|png)$
RewriteCond %{DOCUMENT_ROOT}/%1.webp -f
RewriteRule .* %1.webp [NC,T=image/webp,E=webp,L]

這兩種方法之間唯一真正的區別是,在新方法中,我在檢查文件是否存在的重寫條件之前檢查請求 URI 是否與 jpeg/png 匹配。我認為新方法效率較低,因為重寫規則匹配所有內容,但至少上面的條件過濾了它,並且它在 vhost_ssl.conf 中,它比 .htaccess 更好。

其他一些注意事項:

  • 在測試期間,我將原始重寫更改為 301 重定向,以便我可以看到它認為找到的文件。果然,該文件與 .jpg 文件相同,只是副檔名為 .webp - 正確的路徑和所有文件(即使 .webp 並不真正存在)。
  • 同樣在測試期間,我嘗試將重寫條件更改為RewriteCond %{DOCUMENT_ROOT}/%1.webp_asdfasdfasf -f只是為了驗證它實際上會失敗,並且確實如此。所以它知道完全偽造的文件不存在,但它仍然認為 .webp 文件確實存在。

tl;博士

RewriteCond %{DOCUMENT_ROOT}/%1.webp -f

它應該是$1,不在TestString%1中。雖然目前尚不清楚為什麼這種行為應該只是最近才改變(或者可能沒有改變?)。RewriteCond


RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{DOCUMENT_ROOT}/%1.webp -f
RewriteRule (.+)\.(?:jpe?g|png)$ $1.webp [NC,T=image/webp,E=webp,L]

除非您在文件根目錄中有一個名為 " " 的文件(沒有basename,以點開頭) ,否則這永遠不會奏效。如果你這樣做了,那麼無論它是否存在,它都會將jpeg/png URL 重寫為。.webp``<whatever>.webp

那麼,這似乎表明您.webp在文件根目錄中確實有一個名為(無基本名稱)的文件?(和/或您看到某些請求的記憶體重定向?見下文…)

%1第二個RewriteCond TestString中的反向引用應該是$1,而不是%1%1是對最後匹配的CondPattern中第一個擷取組的反向引用- 其中沒有,因此%1始終為。因此,它將始終測試/path/to/document-root/.webp. $1另一方面是對RewriteRule 模式中第一個擷取的組的反向引用,即。文件系統路徑/基本名稱,不包括文件副檔名。

您已經$1RewriteRule 替換中使用了- 您應該在前面的條件中使用了相同的內容。

請注意,如果這些指令在虛擬主機上下文中,那麼您應該…刪除RewriteCond TestString中的斜杠,例如:

RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{DOCUMENT_ROOT}$1.webp -f
RewriteRule (.+)\.(?:jpe?g|png)$ $1.webp [NC,T=image/webp,E=webp,L]

或者,排除RewriteRule擷取組中的斜線。例如:

RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{DOCUMENT_ROOT}/$1.webp -f
RewriteRule ^/(.+)\.(?:jpe?g|png)$ /$1.webp [NC,T=image/webp,E=webp,L]

否則,您最終會在TestString中出現作業系統需要解析的雙斜杠。

RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_URI} (.+)\.(?:jpe?g|png)$
RewriteCond %{DOCUMENT_ROOT}/%1.webp -f
RewriteRule .* %1.webp [NC,T=image/webp,E=webp,L]

這與在原始規則塊中簡單地使用相同$1(如上所述)。好奇您將替換中的反向引用更改為%1,但知道將條件中的反向引用保持不變(或者這只是被忽略了)?

在測試過程中,我將原來的重寫改成了 301 重定向……

始終使用 302(臨時)重定向進行測試。301 由瀏覽器持久記憶體,因此可能會在以後導致記憶體問題。(事實上,這可以解釋當請求到達瀏覽器記憶體時的“間歇性”行為。)

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