以下是对C# WinForms中使用IHttpClientFactory 和HttpClientFactory 进行高并发网络请求时,处理自定义头和Cookie的方法的修改:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace HttpClientHelper
{
public class HttpClientHelper_
{
private readonly IHttpClientFactory _httpClientFactory;
public HttpClientHelper_(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
public async Task<(string responseContent, string cookie)> SendRequest(string url, string method, string data, string cookie, bool redirection = false, Dictionary<string, string> customHeaders = null, int timeoutSeconds = 50)
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.Timeout = TimeSpan.FromSeconds(timeoutSeconds);
HttpRequestMessage request = new HttpRequestMessage(new HttpMethod(method), url);
// 添加自定义头部
if (customHeaders != null)
{
foreach (var header in customHeaders)
{
request.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
}
// 添加Cookie
if (!string.IsNullOrEmpty(cookie))
{
httpClient.DefaultRequestHeaders.Add("Cookie", cookie);
}
// 如果请求方法为POST,添加请求内容
if (method.Equals("POST", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(data))
{
string contentType = customHeaders != null && customHeaders.ContainsKey("Content-Type") ? customHeaders["Content-Type"] : "application/x-www-form-urlencoded";
request.Content = new StringContent(data, Encoding.UTF8, contentType);
}
HttpResponseMessage response = await httpClient.SendAsync(request);
if (response.IsSuccessStatusCode)
{
string responseContent = await response.Content.ReadAsStringAsync();
string cookieValue = CombineAndUpdateCookie(cookie, ParseNewCookie(response.Headers.GetValues("Set-Cookie")));
return (responseContent, cookieValue);
}
else
{
throw new HttpRequestException($"无法进行 {method} 请求。状态码: {response.StatusCode}");
}
}
static string ParseNewCookie(IEnumerable<string> newCookieHeaders)
{
try
{
Dictionary<string, string> cookieDict = new Dictionary<string, string>();
foreach (var cookieHeader in newCookieHeaders)
{
// 使用正则表达式解析Cookie头部
MatchCollection matches = Regex.Matches(cookieHeader, @"([^=]+)=([^;]+);?");
foreach (Match match in matches)
{
string key = match.Groups[1].Value;
string value = match.Groups[2].Value;
cookieDict[key] = value;
}
}
// 将新Cookie转换为字符串形式
StringBuilder newCookie = new StringBuilder();
foreach (var kvp in cookieDict)
{
newCookie.Append(kvp.Key).Append("=").Append(kvp.Value).Append("; ");
}
return newCookie.ToString();
}
catch (Exception e)
{
Console.WriteLine($"解析新Cookie失败:{e.Message}");
return "";
}
}
static string CombineAndUpdateCookie(string oldCookie, string newCookie)
{
try
{
// 解析旧Cookie
Dictionary<string, string> cookieDict = ParseCookie(oldCookie);
// 解析新Cookie
Dictionary<string, string> newCookieDict = ParseCookie(newCookie);
// 更新旧Cookie中的值或添加新的Cookie项
foreach (var kvp in newCookieDict)
{
cookieDict[kvp.Key] = kvp.Value;
}
// 将合并后的Cookie重新格式化为字符串形式
StringBuilder combinedCookie = new StringBuilder();
foreach (var kvp in cookieDict)
{
combinedCookie.Append(kvp.Key).Append("=").Append(kvp.Value).Append("; ");
}
return combinedCookie.ToString();
}
catch (Exception e)
{
Console.WriteLine($"合并Cookie失败:{e.Message}");
return "";
}
}
static Dictionary<string, string> ParseCookie(string cookie)
{
Dictionary<string, string> cookieDict = new Dictionary<string, string>();
if (!string.IsNullOrEmpty(cookie))
{
try
{
string[] cookieParts = cookie.Split(';', StringSplitOptions.RemoveEmptyEntries);
foreach (string part in cookieParts)
{
string[] keyValue = part.Split('=', 2);
if (keyValue.Length == 2)
{
string key = keyValue[0].Trim();
string value = keyValue[1].Trim();
cookieDict[key] = value;
}
}
}
catch (Exception e)
{
Console.WriteLine($"解析Cookie失败:{e.Message}");
}
}
return cookieDict;
}
}
}
修改内容:
- 将Cookie添加到
httpClient.DefaultRequestHeaders 而不是request.Headers 中。
- 修改了解析
Set-Cookie 头部的方法,以处理多个Cookie头部。
- 更改了从响应头中获取
Set-Cookie 头部的方法。
- 简化了Cookie头部的解析方法。
通过这些修改,应该可以正确地将Cookie包含在请求头中。确保服务器也正确处理Cookie。
|