HttpClient像浏览器一样为cookie分配其他路径信息



我正在使用HttpClient来消费一个网站。网站使用cookie,但其中一个cookie没有分配path数据。HttpClient将使用请求文件的相对路径作为路径信息,而浏览器仅使用目录信息。

示例:

Request-URL:
https://someurl.org/dir1/file.php  
HttpClient:
path=/dir1/file.php  
browser:
path=/dir1  

C#行为是有问题的,因为cookie只会发送到特定的文件,而不是同一目录中的所有文件。作为一种变通方法,我提取cookie,制作一个副本,为副本分配正确的路径,将原始文件标记为过期,然后将副本添加到cookie容器中。

这是可行的,但在这种情况下,可能有一个更好、更正式的选项可以让HttpClient像浏览器一样运行?

这个问题与我自己的问题非常相似(而不是直接使用HttpClient(我的场景(HttpWebRequest(,它也为问题提供了更多的背景信息。

尽管我最终没有得到那里提供的解决方案,但我确实修改了这个问题的答案,以扩展DelegatingHandler并自己管理cookie(如果缺少路径信息,通过插入路径信息来解决问题(,而不是让HttpMessageHandler处理cookie。

public class FixMissingPathOnPlainCookiesHandler : DelegatingHandler
{
public CookieContainer Container { get; private set; }
public FixMissingPathOnPlainCookiesHandler(HttpClientHandler clientHandler, CookieContainer cc = null) 
: base(clientHandler)
{
if (clientHandler == null)
throw new ArgumentNullException(nameof(clientHandler));
if (clientHandler.UseCookies)
throw new InvalidOperationException("The HttpClientHandler property '.UseCookies' must be false");
Container = cc ?? new CookieContainer();
}

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var uri = request.RequestUri;
var cookies = Container.GetCookieHeader(uri);
if (!string.IsNullOrEmpty(cookies))
request.Headers.Add("Cookie", cookies);
var response = await base.SendAsync(request, cancellationToken);
if (response.Headers.TryGetValues("Set-Cookie", out var cookieHeaders))
{
foreach (var cookie in cookieHeaders)
{
var local = cookie;
if (local.IndexOf("path=", StringComparison.InvariantCultureIgnoreCase) == -1)
local += "; path=" + uri.AbsolutePath.Substring(0, uri.AbsolutePath.LastIndexOf('/'));

Container.SetCookies(uri, local);
}
}
return response;
}
}

最新更新