我的网站上有一个端点,我可以从该端点接收来自 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/在浏览器中,它提供了正确的文件。
- 我可以发布到https://www.example.com/auth/foursquare/使用 Postman 或 Insomnia 或任何其他 API 测试工具,它提供了正确的文件。即使我精确地复制了来自 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/ 创建一个符号链接是可行的。但是,这并不能真正解释为什么它突然崩溃了,在我看来,盲目的创可贴解决方案很少是一个好主意。如果导致这种情况的因素还影响了其他因素,而我还没有注意到呢?我想确切地了解发生了什么,为什么它会自发停止工作,以及如何适当地修复它。遗憾的是,很明显,网站托管商(似乎是最有可能的罪魁祸首)不会提供任何帮助。
如果有人有任何想法,我将不胜感激。
答案1
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
标题中(情况应该逆转)。
不要忘记在正则表达式中转义文字点(条件模式)。
^(.*)$
可以简化为,(.*)
因为正则表达式默认是贪婪的。