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;
}
}
我正在使用 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;
}
}