Dot-Htaccess

mod_rewrite 突然不起作用,僅適用於來自 Foursquare API 的傳入 POST 請求

  • January 8, 2020

我的網站上有一個端點,我可以在其中接收來自 FourSquare API 的推送通知。終點是:

https://www.example.com/auth/foursquare/

在伺服器本身上,源文件是:

/home/myusername/public_html/www.example.com/auth/foursquare/index.php

通常,該站點的文件位於:

/home/myusername/public_html/

但我使用 mod_rewrite 將它們放在通常的 webroot 的子目錄中:

/home/myusername/public_html/www.example.com/

這些是 mod_rewrite 規則:

RewriteCond %{HTTP_HOST} ^(www.)?example.com$ [NC]
RewriteRule ^(.*)$ /www.example.com/$1 [L]

到現在為止還挺好。一切都是這樣工作的,並且多年來一直沒有問題。直到幾個月前,FourSquare 的推送突然停止了。對伺服器錯誤日誌的調查表明,由於某種原因,它現在正試圖從原始(非重寫)路徑提供文件:

2019-12-30 00:26:31.383141 [INFO] [34.231.230.177:15669] File not found [/home/myusername/public_html/auth/foursquare/]
2019-12-30 00:26:31.383256 [INFO] [34.231.230.177:15669] File not found [/home/myusername/public_html/404.shtml]

真正奇怪的是,這只發生在傳入請求來自foursquare API本身時:

  • 我可以在瀏覽器中訪問 https://www.example.com/auth/foursquare/,它提供了正確的文件。
  • 我可以使用 Postman 或 Insomnia 或任何其他 API 測試工具發佈到https://www.example.com/auth/foursquare/,它會提供正確的文件。即使我精確地複制了 FourSquare 的標頭和 POST 數據(我通過更改 FourSquare 應用程序以推送到 hookbin 端點來確定,這樣我就可以檢查它們發送的確切數據)。

我能想到的唯一共同點就是源IP;當 POST 來自 FourSquare 的 IP 時,mod_rewrite 不提供來自子目錄的預期文件 - 但來自所有其他 IP。雖然顯然我沒有任何特定於 IP 的規則會導致這種情況,所以這沒有任何意義。

因為在很長一段時間內我沒有更改任何程式碼或 htaccess 規則(即早在這自發開始發生之前),因此我的(共享)虛擬主機必須更改了一些破壞它的伺服器配置。但我已經與他們交換了 20 多條消息,他們只是不斷地回复“我們不知道為什麼會發生這種情況,只需從原始路徑創建一個符號連結就可以了。” 確實,從 /home/myusername/public_html/auth/ 到 /home/myusername/public_html/www.example.com/auth/ 的符號連結有效。然而,這並不能解釋為什麼它會突然壞掉,而且 IMO 的盲目創可貼解決方案很少是一個好主意。如果這件事發生的任何事情也影響了其他事情,我還沒有幸運地註意到呢?一世’正確修復它。可悲的是,很明顯,網路主機 - 這似乎是最有可能的罪魁禍首 - 將無濟於事。

如果有人有任何想法,我將不勝感激。

Reqhost 設置為:“www.example.com:443”

這似乎肯定是問題的原因。儘管為什麼埠(正在發送請求)現在出現在Host標頭中是另一回事。443是 HTTPS 的預設埠。但是,由於它是預設埠,因此它不需要出現Host標頭中。如果您從非標準埠提供內容,則只需要指定的埠。

FourSquare 可能已經開始偷偷包含埠號作為請求的一部分(假設這沒有被錯誤地設置在 FourSquare 的配置中?) - 儘管這可能是不正確的(儘管嚴格來說不違反規範)因為它將限制您的伺服器使用預設埠(您應該能夠使用您想要的任何埠)。

另一種可能性是您有一個(新的)前端代理,它可能會將埠號附加到轉發到您的應用程序伺服器的請求中。但這不太可能,因為它可能會影響所有請求,並且從您的測試中,情況並非如此。

“修復”似乎是允許請求中的埠號(假設只有埠 443 而不是埠 80 - 純 HTTP)。

例如:

RewriteCond %{HTTP_HOST} ^(www\.)?example\.com(:443)?$ [NC]
RewriteRule (.*) /www.example.com/$1 [L]

(:443)?使埠號在標頭中可選Host(如果情況相反)。

不要忘記在正則表達式(CondPattern)中轉義文字點。

^(.*)$可以簡化為,(.*)因為正則表達式預設是貪婪的。

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