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

HttpClient assigns other path information to cookies as browsers do

我正在使用 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 像浏览器一样运行?

This 问题与我自己的问题非常相似(而不是 HttpClient (我的场景)直接使用 HttpWebRequest )并且它还为问题提供了更多背景信息。

尽管如此,我并没有得到那里提供的解决方案,我确实修改了 this 问题的答案以扩展 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;
    }
}