C# HttpClient.SendAsync 总是返回 404 但 URL 在浏览器中有效

Posted

技术标签:

【中文标题】C# HttpClient.SendAsync 总是返回 404 但 URL 在浏览器中有效【英文标题】:C# HttpClient.SendAsync always returns 404 but URL works in browser 【发布时间】:2015-11-05 21:08:45 【问题描述】:

我正在开发一个 C# 控制台应用程序来测试 URL 是否有效。它适用于大多数 URL。但我们发现在某些情况下,应用程序总是从目标站点获得 404 响应,但 URL 实际在浏览器中有效。当我在 DHC(Dev HTTP 客户端)等工具中尝试这些 URL 时,它们也可以工作。

一开始,我认为这可能是没有添加正确标题的原因。但是在尝试使用 Fiddler 编写具有相同标头的 http 请求后,它可以在 Fiddler 中使用。

那么我的代码有什么问题? .NET HttpClient 中是否有任何错误?

这是我的测试应用程序的简化代码:

class Program

    static void Main(string[] args)
    
        var urlTester = new UrlTester("http://www.hffa.it/short-master-programs/fashion-photography");

        Console.WriteLine("Test is started");

        Task.WhenAll(urlTester.RunTestAsync());

        Console.WriteLine("Test is stoped");
        Console.ReadKey();
    


    public class UrlTester
    
        private HttpClient _httpClient;
        private string _url;

        public UrlTester(string url)
        
            _httpClient = new HttpClient 
             
                Timeout = TimeSpan.FromMinutes(1)
            ;

            // Add headers
            _httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/46.0.2490.80 Safari/537.36");
            _httpClient.DefaultRequestHeaders.Add("Accept-Encoding", "gzip,deflate,sdch");
            _httpClient.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
            _httpClient.DefaultRequestHeaders.Add("Accept-Language", "sv-SE,sv;q=0.8,en-US;q=0.6,en;q=0.4");

            _url = url;
        

        public async Task RunTestAsync()
        
            var httpRequestMsg = new HttpRequestMessage(HttpMethod.Get, _url);

            try
            
                using (var response = await _httpClient.SendAsync(httpRequestMsg, HttpCompletionOption.ResponseHeadersRead))
                
                    Console.WriteLine("Response: 0", response.StatusCode);
                
            
            catch (HttpRequestException e) 
            
                Console.WriteLine(e.InnerException.Message);
            
        
    


【问题讨论】:

您从该代码中得到的究竟是什么? 一个HTTP请求就是一个HTTP请求;它来自哪里并不重要(除非服务器阻止某些 User-Agent 标头,但即使这也可以更改)。这确实对我来说听起来像是一个标题问题。您是否确认您正在完全复制从浏览器发送的请求?您是否使用过像 Fiddler 这样的工具来准确捕获 HTTP 流量,然后将其复制到您的代码中? @pymaxion 是的。我照你说的做了。我使用 Fiddler 来查看成功的 http 请求中标头的外观。然后在代码中添加这些标题。即使我后来得到了类似的标题,它仍然没有用。 我建议你运行一个像 Wireshark 这样的网络嗅探器,看看到底发生了什么。也许异步客户端也发送了Expect: 100-continue 标头? @RonKlein 嗨,我尝试添加 _client.DefaultRequestHeaders.ExpectContinue = false,仍然得到 404。 【参考方案1】:

这似乎是接受的语言的问题。使用以下 Accept-Language 标头值时收到 200 响应

_httpClient.DefaultRequestHeaders.Add("Accept-Language", "en-GB,en-US;q=0.8,en;q=0.6,ru;q=0.4");

附言我假设您知道在您的示例中 _client 应该在 urlTester 构造函数中读取 _httpClient 否则它不会构建。

【讨论】:

【参考方案2】:

此问题的另一个可能原因是您发送的 url 长度超过大约 2048 个字节。此时内容(几乎可以肯定是查询字符串)可能会被截断,这反过来意味着它可能无法与服务器端路由正确匹配。

虽然这些 url 在浏览器中被正确处理,但在 power shell 中使用 get 命令也失败了。

通过使用带有键值对的 POST 而不是使用带有长查询字符串的 GET 解决了这个问题。

【讨论】:

以上是关于C# HttpClient.SendAsync 总是返回 404 但 URL 在浏览器中有效的主要内容,如果未能解决你的问题,请参考以下文章

在 HttpClient.SendAsync() 之后无法访问已释放的对象

HttpClient.SendAsync() 未将 JSON 作为字符串发送

HttpClient.SendAsync 不发送请求正文

HttpClient.SendAsync 方法退出而不抛出异常

HttpClient SendAsync

模拟 HttpClient.SendAsync 以返回内容不为空的响应