【问题标题】:HttpClient GetAsync with a hash in URLHttpClient GetAsync 与 URL 中的哈希
【发布时间】:2019-01-03 15:47:40
【问题描述】:

Windows 上的 .NET Core 2.2 控制台应用程序。

我正在探索如何在 Stackoverflow 共享样式 URL 上使用 HttpClient GetAsync,例如:https://stackoverflow.com/a/29809054/26086,它返回一个带有哈希的 302 重定向 URL

static async Task Main()
{
    var client = new HttpClient();

    // 1. Doesn't work - has a hash in URL
    var url = "https://stackoverflow.com/questions/29808915/why-use-async-await-all-the-way-down/29809054#29809054";
    HttpResponseMessage rm = await client.GetAsync(url);
    Console.WriteLine($"Status code: {(int)rm.StatusCode}"); // 400 Bad Request

    // 2. Does work - no hash
    url = "https://stackoverflow.com/questions/29808915/why-use-async-await-all-the-way-down/29809054";
    rm = await client.GetAsync(url);
    Console.WriteLine($"Status code: {(int)rm.StatusCode}"); // 200 Okay

    // 3. Doesn't work as the 302 redirect goes to the first URL above with a hash
    url = "https://stackoverflow.com/a/29809054/26086";
    rm = await client.GetAsync(url);
    Console.WriteLine($"Status code: {(int)rm.StatusCode}"); // 400 Bad Request
}

我正在爬我的博客,里面有很多这么短的代码。

更新/解决方法 感谢@rohancragg,我发现关闭 AutoRedirect 然后从返回的标头中获取 URI 是可行的

// as some autoredirects fail due to #fragments in url, handle redirects manually
var handler = new HttpClientHandler { AllowAutoRedirect = false };
var client = new HttpClient(handler);

var url = "https://stackoverflow.com/a/29809054/26086";    
HttpResponseMessage rm = await client.GetAsync(url);

// gives the desired new URL which can then GetAsync
Uri u = rm.Headers.Location;

【问题讨论】:

  • 发送到服务器的 URL 不包含 # 片段。它仅在客户端中使用,例如浏览器。
  • 有道理,谢谢。我正在研究为什么它现在给出 400,因为我希望 HttpClient 忽略散列。我已更新问题以突出显示我需要这样做的原因,即 StackOverflow 共享网址。
  • 正如@Damien_The_Unbeliever 所暗示的那样,您只需要去掉散列和之后的所有内容 - 所做的就是告诉浏览器跳转到 HTML 页面中的锚标记(请参阅:@987654322 @)。所以这意味着在这种情况下,您的选项 2 是您唯一的选择...
  • 您也可以使用 Uri 类来解析 Uri 并忽略任何“片段”:docs.microsoft.com/en-us/dotnet/api/system.uri.fragment
  • 谢谢@rohancragg - 但是如果我请求stackoverflow.com/a/29809054/26086 然后返回302,并自动请求其中包含哈希的URL。也许我必须停止自动重定向stackoverflow.com/a/10647245/26086,然后去掉哈希,然后再做一个请求。

标签: c# http url .net-core


【解决方案1】:

正如@Damien_The_Unbeliever 在评论中所暗示的那样,您只需要去掉散列和之后的所有内容 - 所做的只是告诉浏览器跳转到 HTML 页面中的锚标记(请参阅:https://w3schools.com/jsref/prop_anchor_hash.asp) .

您还可以使用 Uri 类来解析 Uri 并忽略任何“片段”:https://docs.microsoft.com/en-us/dotnet/api/system.uri.fragment

因为共享样式的 Url 只会返回 302,所以我建议捕获 302 所指的 Uri,并按照我上面的建议进行操作,然后获取路径并忽略片段。

所以你需要使用一些机制(我只是在查找!)来优雅地处理 302,然后是选项 2

更新:这看起来很相关! How can I get System.Net.Http.HttpClient to not follow 302 redirects?

更新 2 Steve Guidi 在这里的评论中有一个非常重要的建议:https://stackoverflow.com/a/17758758/5351

响应您需要使用HttpResponseMessage.RequestMessage.RequestUri的建议:

添加HttpCompletionOption.ResponseHeadersRead很重要 作为GetAsync()调用的第二个参数


免责声明 - 我没有尝试以上,这只是基于阅读;-)

【讨论】:

    【解决方案2】:

    也许您需要在使用 HttpUtility 类发送请求之前对您的 URL 进行编码,这样任何特殊字符都会被转义。

    using System.Web;
    
    var url = $"htpps://myurl.com/{HttpUtility.UrlEncode("#1234567")}";
    

    【讨论】:

    • 谢谢你,Vinick - 我认为我需要另一种策略来将 HttpClient 弯曲成我想要它做的事情,即当我给出一个 URL 时正确响应:stackoverflow.com/a/29809054/26086
    猜你喜欢
    • 2016-04-20
    • 2013-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    • 2015-08-04
    相关资源
    最近更新 更多