【问题标题】:Why does a HttpClient GET time out for Staples.com?为什么 Staples.com 的 HttpClient GET 超时?
【发布时间】:2018-05-25 16:47:19
【问题描述】:

我正在 .NET Core 2.0 控制台应用程序中尝试对域的非常简单的 GET 请求:

static void Main(string[] args)
{
    MainAsync().Wait();
}

static async Task MainAsync()
{
    var httpClient = new HttpClient();
    var response = await httpClient.GetAsync("https://www.staples.com");
}

每次都会超时,抛出网络异常。

我可以在我的网络浏览器中访问网站https://www.staples.com 或在邮递员中执行 GET 请求而没有问题,在

我什至可以在域上做一个简单的 curl 请求,它工作正常:

curl https://www.staples.com

我发现同样问题的另一个域是https://www.safeco.com/

我什至尝试添加一些标头以使其看起来像 Chrome 浏览器请求,但没有任何区别:

message.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
  "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36");
message.Headers.Add("Accept-Language", "en-US,en;q=0.8");
message.Headers.Add("Cache-Control", "no-cache");
message.Headers.Add("Pragma", "no-cache");
message.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;" +
  "q=0.9,image/webp,image/apng,*/*;q=0.8");

我没有在这些域上尝试过的任何其他 URL 似乎都可以正常工作。为什么这两个域会因 HttpClient 请求而超时?

【问题讨论】:

  • 我假设当您添加这些标头时,您是 SendAsync'ing HttpRequestMessage 而不是您在问题中显示的代码?
  • @Crowcoder 是的,我只是在使用 sn-ps,而不是过于冗长。
  • 我们应该如何确定为什么会发生这种情况?我的猜测是防止刮板,但只有 Staples 可以回答这个问题。
  • @DavidG 相同参数的邮递员请求和HttpClient请求有什么区别?为什么一个有效,另一个无效?
  • @kspearrin 我不同意,没有它我们无法帮助您。在我们建议对您的代码进行更改之前,我们需要查看线路上有什么不同。 Something 在工作请求和非工作请求之间是不同的。我们需要请求来查看那是什么——而不是您的代码。

标签: c# .net .net-core


【解决方案1】:

几乎可以肯定,他们会在他们的一端进行某种连接过滤以防止抓取,但只有他们的 IT 部门才能确认这一点。您可以通过模仿浏览器并发送正确的标头来使其工作。看来这个网站至少需要:

Connection: keep-alive
Accept-Encoding: gzip
Accept-Language: xxx

例如:

static async Task<string> MainAsync()
{
    //Added this to decompress the gzip encoded response
    HttpClientHandler handler = new HttpClientHandler();
    handler.AutomaticDecompression = System.Net.DecompressionMethods.GZip;

    var client = new HttpClient(handler);
    var request = new HttpRequestMessage()
    {
        Method = HttpMethod.Get, 
        RequestUri = new Uri("https://www.staples.com"),
        Version = new Version(1, 1)
    };

    request.Headers.Connection.Add("keep-alive");
    request.Headers.AcceptLanguage.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("en-GB"));

    var response = await client.SendAsync(request);
    return await response.Content.ReadAsStringAsync();
}

【讨论】:

  • 还发现添加Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36之类的用户代理也会导致请求被阻塞。
  • 对我来说,仅设置与 curl 相同的用户代理已经允许请求通过
【解决方案2】:

不是答案,但也不适合发表评论-也许您可以通过将其添加到配置中来从网络跟踪中收集一些东西。只需将initializeData 的值更改为可写位置,发出请求,然后查看输出。不漂亮,但可能有线索。

  <system.diagnostics>
    <sources>
      <source name="System.Net" maxdatasize="102400" tracemode="includehex">
        <listeners>
          <add name="System.Net" />
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="System.Net" value="Verbose" />
    </switches>
    <sharedListeners>
      <add name="System.Net" type="System.Diagnostics.TextWriterTraceListener" initializeData="c:\somewhere...\networkErr.log" />
    </sharedListeners>
  </system.diagnostics>

【讨论】:

  • 您可以发表评论,其中包含指向此代码的链接。 IMO 这是处理此问题的最佳方式。
猜你喜欢
  • 2020-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-09
  • 2020-08-20
  • 2021-03-19
  • 2018-04-22
相关资源
最近更新 更多