我一直在开发一个确定网页信息的应用程序。其中一个组件涉及向URL发出HTTP请求,获取HTML并对其进行分析。我抛给它的每个URL都很好,除了一个.
罪魁祸首是.NET HttpClient,它似乎总是超时请求问题域中的任何URL。但是,使用浏览器请求的同一个URL在毫秒内返回内容。没有任何关于标题的不寻常之处。
增加超时只会导致爆炸需要更长的时间。我试过几分钟也有同样的结果。我尝试过各种方法,比如将用户代理字符串设置为Chrome,但没有效果。
所讨论的域是:http://careers.adidas-group.com,注意,相同的站点也在https://careers.adidas-group.com的HTTPS上运行(它有一个有效的证书)。使用任何一种协议都会导致相同的错误。
我可以用一个简单的C#控制台应用程序来显示问题,如下所示:
static void Main(string[] args)
{
string url = "http://careers.adidas-group.com";
var client = new HttpClient
{
Timeout = TimeSpan.FromSeconds(10)
};
using (var message = new HttpRequestMessage(HttpMethod.Get, url))
{
using (var httpResponse = Task.Run(() => client.SendAsync(message)).Result)
{
Console.WriteLine("{0}: {1}", httpResponse.StatusCode, httpResponse.ReasonPhrase);
}
}
Console.ReadLine();
}注意,在上面的示例中,我将超时设置为10秒,只是为了加速问题--但是,增加超时并没有什么区别。
具有不同URL (如https://stackoverflow.com/)的相同代码运行良好。
还请注意,上面的代码被简化为作为控制台应用程序运行。我的实际代码在异步MVC控制器方法中异步运行(使用等待)--我只是使用Task.Run(() => )使它在示例中与同步主方法的上下文一起工作。但这对结果没有任何影响。(实际的例外是“任务被取消”,但这似乎是对超时的同情,而不是实际的问题)。
有人能向我解释一下为什么会发生这种情况(是关于服务器配置的吗?)如果有的话,我能做些什么来让HttpClient满足这个请求呢?谢谢。
发布于 2018-02-14 16:22:27
好的,经过大量的调查,我决定一定是服务器在请求中寻找特定的头。因此,我检查了大多数浏览器发送的内容,复制了这些内容,最后将其压缩到服务器上,要求出现以下所有标题:
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate");
client.DefaultRequestHeaders.Add("Accept-Language", "en-GB,en;q=0.9,en-US;q=0.8");如果删除其中任何一个,服务器就不会响应。很奇怪!
感谢所有看过这篇文章的人,我希望这个答案能对将来的人有所帮助:)
编辑-更古怪的
好的,奇怪的事情现在还在继续,因为尽管这解决了本地运行的问题(在VS 2017中使用IIS Express),但在部署到活动环境(在IIS 7.5 / Windows Server中运行)时,它仍然不能工作。与控制台应用程序版本一样--在本地PC上工作,在服务器上不工作。尝试了3台Windows服务器,相同的代码,它工作在一个,而不是在其他两个。比扎雷。
进一步编辑-一个决议?
因此,在进一步阅读后,它似乎出现了某些web服务器,例如akamai幽灵(它承载了所讨论的域)有一些相当复杂的"bot“检测,它拒绝来自未知客户端的连接。措施包括检查HTTP请求头的顺序,以便它们与用户代理通常发送的内容相匹配(即。如果您伪造用户代理字符串为Chrome,您最好的行为与Chrome完全一样,按照chrome的顺序发送标头,并接受相同的内容类型等等)。
在尝试过伪造大量浏览器用户代理字符串之后,我最终发现“假装”是Google PageSpeed机器人的效果很好。将用户代理字符串设置为:"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko; Google Page Speed Insights) Chrome/27.0.1453 Safari/537.36“
不管使用的是哪个版本的Windows或.NET框架,这似乎都是有效的。
我最终想出的标题是:
this.Client.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/apng,*/*;q=0.8");
this.Client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
this.Client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
this.Client.DefaultRequestHeaders.Add("Accept-Language", "en-GB,en;q=0.9,en-US;q=0.8");
this.Client.DefaultRequestHeaders.Add("Connection", "keep-alive");
this.Client.DefaultRequestHeaders.Add("Cache-Control", "no-cache");
this.Client.DefaultRequestHeaders.Add("Pragma", "no-cache");
this.Client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko; Google Page Speed Insights) Chrome/27.0.1453 Safari/537.36");发布于 2018-03-05 14:28:21
你想出的答案是正确的。但是,为了以后的注意,我建议使用像Charles或Fiddler这样的web调试器。它使复制请求变得更容易,并最终找到为什么您没有从主机获得任何响应的根本原因。在这个例子中,我使用了Charles。

从我的中,我可以看到客户机"DefaultHeaders“都是空的。因此,正如OP已经展示的那样,我们所需要做的就是将头添加到我们的客户端,并希望它满足主机的需求。
static void Main(string[] args)
{
string url = "http://careers.adidas-group.com";
var client = new HttpClient
{
Timeout = TimeSpan.FromSeconds(10)
};
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate");
client.DefaultRequestHeaders.Add("Accept-Language", "en-US,en;q=0.5");
client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0");
client.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
using (var message = new HttpRequestMessage(HttpMethod.Get, url))
{
using (var httpResponse = Task.Run(() => client.SendAsync(message)).Result)
{
Console.WriteLine("{0}: {1}", httpResponse.StatusCode, httpResponse.ReasonPhrase);
}
}
Console.ReadLine();
}我只想补充一下我所知道的对于大多数主人来说是必不可少的。通过测试上面的代码,我们得到了一个代码'OK : OK‘。如果我们试图删除这些行中的任何一行:
client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate");
client.DefaultRequestHeaders.Add("Accept-Language", "en-US,en;q=0.5");
client.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");我们将再次陷入无止境的循环。这意味着主机不关心您使用的是什么用户代理。阿迪达斯的robots.txt(https://careers.adidas-group.com/robots.txt)也表明了这一点(因为数据矿工是不使用浏览器的自动化服务),阿迪达斯不介意在他们的领域里有几个蜘蛛/数据矿工。
https://stackoverflow.com/questions/48790438
复制相似问题