Apache-2.2

你能在我的 .htaccess 中看到什麼問題嗎?

  • August 10, 2020

我已經設法創建了一個.htaccess文件,可以滿足我的要求(請參閱程式碼塊後的解釋和問題):

<IfModule mod_rewrite.c>

RewriteEngine On

#1 If the requested file is not url-mapper.php (to avoid .htaccess loop)
RewriteCond %{REQUEST_FILENAME} (?<!url-mapper\.php)$

#2 If the requested URI does not end with an extension OR if the URI ends with .php*
RewriteCond %{REQUEST_URI} !\.(.*) [OR]
RewriteCond %{REQUEST_URI} \.php.*$ [NC]

#3 If the requested URI is not in an excluded location
RewriteCond %{REQUEST_URI} !^/seo-urls\/(excluded1|excluded2)(/.*)?$

#Then serve the URI via the mapper
RewriteRule .* /seo-urls/url-mapper.php?uri=%{REQUEST_URI} [L,QSA]

</IfModule>

這是.htaccess應該做的:

  1. Rule#1正在檢查請求的文件是否不是url-mapper.php(以避免無限重定向循環)。此文件將始終位於域的根目錄。
  2. 規則#2.htaccess必須只擷取不以副檔名結尾的 URL ( – www.example.com> catch | www.example.com/catch-me–> catch | www.example.com/dont-catch.me–> don’t catch).php\*以文件結尾的 URL ( .php, .php4, .php5, .php123, …)。
  3. 規則#3一些目錄(和子目錄)可以從.htaccess(在這種情況下/seo-urls/excluded1/seo-urls/excluded2)中排除。
  4. 最後,.htaccess向映射器提供一個隱藏的GET 參數,該參數名為uri包含請求的 URI。

即使我進行了測試並且一切正常,我也想知道我所做的是否正確(以及它是否是“最好的”方法)。我從這個“項目”中學到了很多東西,但我仍然認為自己是.htaccess正則表達式的初學者,所以我想在將其投入生產之前對其進行三次檢查……

2a 將允許 /some.dir/file 因為“。” 在中間。您可能想要類似的東西!\..[1,3],這取決於您的文件/目錄結構。

在 RewriteRules 中,使用替換匹配而不是變數名是正常的:

RewriteRule (.*) /seo-urls/url-mapper.php?uri=$5 [L,QSA]

注意這是$5因為您目前在您的條件中都有匹配模式。

<IfModule mod_rewrite.c>

不需要<IfModule>包裝器。在網站管理員堆棧上查看此問題: https ://webmasters.stackexchange.com/questions/112600/is-checking-for-mod-write-really-necessary

#1 If the requested file is not url-mapper.php (to avoid .htaccess loop)
RewriteCond %{REQUEST_FILENAME} (?<!url-mapper\.php)$

不需要消極的後視 ( (?<!)。最好簡單地使用一個否定的正則表達式。IE。帶!前綴。例如:!^/url-mapper\.php$(ie. not “/url-mapper.php”) 並檢查REQUEST_URI(full URL-path) 而不是REQUEST_FILENAME(absolute filesystem path)。

但是,您聲明“此文件將始終位於域的根目錄”,但您正在重寫/seo-urls/url-mapper.php- 它不在域的根目錄。

所以,這應該嚴格地寫成這樣:

RewriteCond %{REQUEST_URI} !^/seo-urls/url-mapper\.php$

除非您確信url-mapper.php系統上只有一個文件,否則正則表達式可以簡化為!/url-mapper\.php$.

或者,改為在RewriteRule 模式中檢查這一點(因為您目前沒有對RewriteRule 模式執行任何其他操作)。這會稍微更有效率。

#2 If the requested URI does not end with an extension OR if the URI ends with .php*
RewriteCond %{REQUEST_URI} !\.(.*) [OR]
RewriteCond %{REQUEST_URI} \.php.*$ [NC]

第一個條件太籠統了——它擷取任何在 URL 路徑中任何地方都包含一個點的 URL,而不僅僅是文件副檔名。也不需要擷取子模式。假設文件副檔名介於 2 到 4 個字元之間,那麼類似的模式!\.\w{2,4}$將更準確地僅擷取文件副檔名。

正則表達式通常應盡可能嚴格。匹配 副檔名的第二個條件.php可以更加嚴格,它目前匹配URL 路徑中的.php *任何位置。*例如:\.php\d{0,4}$- 雖然實際上,您可能最多只有 1 位數字.php,所以\.php\d?$可能會更好。

我還質疑NC這裡是否真的需要(不區分大小寫)標誌。你真的需要匹配嗎.PHP.PhP

#3 If the requested URI is not in an excluded location
RewriteCond %{REQUEST_URI} !^/seo-urls\/(excluded1|excluded2)(/.*)?$

好的,但尾隨(/.*)?$是多餘的。您正在匹配任何簡單開始/seo-urls/excluded1等的內容。此外,無需反斜杠轉義斜杠(好奇您已經轉義了中間斜杠,但不是其他兩個)。

#Then serve the URI via the mapper
RewriteRule .* /seo-urls/url-mapper.php?uri=%{REQUEST_URI} [L,QSA]

好的,雖然正則表達式.*(匹配所有內容)可以簡化為^- 這對所有內容都是成功的,但實際上並不匹配任何內容 - 這就是您所需要的。

但是,我在頂部提到了在模式url-mapper.php中執行檢查。所以,這將被寫成:RewriteRule

RewriteRule !^seo-urls/url-mapper\.php$ /seo-urls/url-mapper.php?uri=%{REQUEST_URI} [L,QSA]

在任何條件之前首先處理RewriteRule 模式,因此最好在RewriteRule指令中執行您可以執行的操作,而不是將其分離到另一個條件中。

概括

綜合以上幾點,我們有:

RewriteEgnine On

#2 If the requested URI does not end with an extension OR if the URI ends with .php*
RewriteCond %{REQUEST_URI} !\.\w{2,4}$ [OR]
RewriteCond %{REQUEST_URI} \.php\d?$

#3 If the requested URI is not in an excluded location
RewriteCond %{REQUEST_URI} !^/seo-urls\/(excluded1|excluded2)

#Then serve the URI via the mapper
RewriteRule !^seo-urls/url-mapper\.php$ /seo-urls/url-mapper.php?uri=%{REQUEST_URI} [QSA,L]

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