为什么C# HttpClient无法调用这个URL(总是超时)?

2024-03-11

我一直在开发一个确定网页信息的应用程序。其中的组成部分之一涉及向 URL 发出 HTTP GET 请求、抓取 HTML 并对其进行分析。这对于我向它抛出的每个 URL 都运行良好,除了一个......

罪魁祸首是.NETHttpClient请求问题域内的任何 URL 似乎总是超时。然而,使用浏览器请求的相同 URL 在几毫秒内就会返回内容。标题似乎没有什么异常。

增加超时只会导致爆炸需要更长的时间。我已经尝试了几分钟,结果相同。我尝试过各种方法,例如将用户代理字符串设置为 Chrome 的字符串,但没有成功。

有问题的域是:http://careers.adidas-group.com http://careers.adidas-group.com请注意,同一站点也运行在 HTTPS 上:https://careers.adidas-group.com https://careers.adidas-group.com(它有有效的证书)。 使用任一协议都会导致相同的错误。

我可以使用一个简单的 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/ https://stackoverflow.com/)运行良好。

另请注意,上面的代码已简化为作为控制台应用程序运行。我的实际代码在异步 MVC 控制器方法中正确异步运行(使用等待) - 我只是使用Task.Run(() => )使其在示例中的同步 Main 方法的上下文中工作。但这对结果没有影响。 (实际的异常是“任务被取消”,但这似乎是超时的症状,而不是实际的问题)。

谁能向我解释为什么会发生这种情况(与服务器配置有关吗?)以及我可以做什么(如果有的话)来使 HttpClient 满足请求?谢谢。


好的,经过大量调查后,我决定必须由服务器在请求中查找特定标头。因此,我检查了大多数浏览器发送的内容,复制了这些内容,然后最终将其缩减为需要的服务器all存在以下标题:

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 服务器,相同的代码,它在其中一台上运行,但在另外两台上不起作用。太奇怪了。

进一步编辑 - 决议?

所以进一步阅读后出现某些网络服务器 https://gwillem.gitlab.io/2017/05/02/http-header-order-is-important/, 例如阿卡迈幽灵(托管有问题的域)有一些相当复杂的“机器人”检测,它拒绝来自未知客户端的连接。措施包括检查 HTTP 请求标头的顺序,以便它们与用户代理通常发送的内容匹配(即,如果您将用户代理字符串伪造为 Chrome,则最好采取行动)exactly像 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 Framework,这似乎都有效。

我最终想出的标题是:

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");
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么C# HttpClient无法调用这个URL(总是超时)? 的相关文章

  • 如何捕获未发送到 stdout 的命令行文本?

    我在项目中使用 LAME 命令行 mp3 编码器 我希望能够看到某人正在使用什么版本 如果我只执行 LAME exe 而不带参数 我会得到 例如 C LAME gt LAME exe LAME 32 bits version 3 98 2
  • GetType() 在 Type 实例上返回什么?

    我在一些调试过程中遇到了这段代码 private bool HasBaseType Type type out Type baseType Type originalType type GetType baseType GetBaseTyp
  • IdentityServer 4 对它的工作原理感到困惑

    我阅读和观看了很多有关 Identity Server 4 的内容 但我仍然对它有点困惑 因为似乎有很多移动部件 我现在明白这是一个单独的项目 它处理用户身份验证 我仍然不明白的是用户如何注册它 谁存储用户名 密码 我打算进行此设置 Rea
  • 如何判断计算机是否已重新启动?

    我曾经使用过一个命令行 SMTP 邮件程序 作为试用版的限制 它允许您在每个 Windows 会话中最多接收 10 封电子邮件 如果您重新启动计算机 您可能还会收到 10 个以上 我认为这种共享软件破坏非常巧妙 我想在我的应用程序中复制它
  • 从同一个类中的另一个构造函数调用构造函数

    我有一个带有两个构造函数的类 C 这是代码片段 public class FooBar public FooBar string s constructor 1 some functionality public FooBar int i
  • 如何记录进入 IIS 的 HTTP 请求

    我在我的开发机器上运行 IIS 5 我有一个 asp net 3 5 Web 服务在其上运行 我从同一服务器上运行的不同 Web 应用程序调用该服务 我的服务返回错误 500 内部服务器错误 我正在对其进行故障排除 我的请求是通过Syste
  • 查看 NuGet 包依赖关系层次结构

    有没有一种方法 文本或图形 来查看 NuGet 包之间的依赖关系层次结构 如果您使用的是新的 csproj 您可以在此处获取所有依赖项 在项目构建后 项目目录 obj project assets json
  • Visual Studio 在构建后显示假错误

    我使用的是 Visual Studio 2017 构建后 sln在调试模式下 我收到错误 但是 当我通过双击错误列表选项卡中的错误来访问错误时 错误会从页面中消失 并且错误数量也会减少 我不太确定这种行为以及为什么会发生这种情况 有超过 2
  • 从客户端访问 DomainService 中的自定义对象

    我正在使用域服务从 Silverlight 客户端的数据库中获取数据 在DomainService1 cs中 我添加了以下内容 EnableClientAccess public class Product public int produ
  • 类型约束

    我有以下类层次结构 class Header IEnumerable
  • 使用valgrind进行GDB远程调试

    如果我使用远程调试gdb我连接到gdbserver using target remote host 2345 如果我使用 valgrind 和 gdb 调试内存错误 以中断无效内存访问 我会使用 target remote vgdb 启动
  • IQueryable 单元或集成测试

    我有一个 Web api 并且公开了一个端点 如下所示 api 假期 name name 这是 Web api 的控制器 get 方法 public IQueryable
  • 保护 APK 中的字符串

    我正在使用 Xamarin 的 Mono for Android 开发一个 Android 应用程序 我目前正在努力使用 Google Play API 添加应用内购买功能 为此 我需要从我的应用程序内向 Google 发送公共许可证密钥
  • 高效列出目录中的所有子目录

    请参阅迄今为止所采取的建议的编辑 我正在尝试使用 WinAPI 和 C 列出给定目录中的所有目录 文件夹 现在我的算法又慢又低效 使用 FindFirstFileEx 打开我正在搜索的文件夹 然后我查看目录中的每个文件 使用 FindNex
  • 检测到严重错误 c0000374 - C++ dll 将已分配内存的指针返回到 C#

    我有一个 c dll 它为我的主 c 应用程序提供一些功能 在这里 我尝试读取一个文件 将其加载到内存 然后返回一些信息 例如加载数据的指针和内存块的计数到 c Dll 成功将文件读取到内存 但在返回主应用程序时 程序由于堆损坏而崩溃 检测
  • WPF DataGridTemplateColumn 组合框更新所有行

    我有这个 XAML 它从 ItemSource 是枚举的组合框中选择一个值 我使用的教程是 http www c sharpcorner com uploadfile dpatra combobox in datagrid in wpf h
  • 使 Guid 属性成为线程安全的

    我的一个类有一个 Guid 类型的属性 该属性可以由多个线程同时读写 我的印象是对 Guid 的读取和写入不是原子的 因此我应该锁定它们 我选择这样做 public Guid TestKey get lock testKeyLock ret
  • 实体框架中的“it”是什么

    如果以前有人问过这个问题 请原谅我 但我的任何搜索中都没有出现 它 我有两个数据库表 Person 和 Employee 对每个类型的表进行建模 例如 Employee is a Person 在我的 edmx 设计器中 我定义了一个实体
  • 堆栈是向上增长还是向下增长?

    我在 C 中有这段代码 int q 10 int s 5 int a 3 printf Address of a d n int a printf Address of a 1 d n int a 1 printf Address of a
  • 如何使用 C++11 using 语法键入定义函数指针?

    我想写这个 typedef void FunctionPtr using using 我该怎么做呢 它具有类似的语法 只不过您从指针中删除了标识符 using FunctionPtr void 这是一个Example http ideone

随机推荐