我需要发送带有自定义标头列表的 HTTP 请求。这些标头可能具有具有不同值的重复键。我正在从事 .NET Framework 项目。
到目前为止,我已经尝试使用 HttpClient 并添加相同的关键标头:
using (var client = new HttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:8080/api/test");
request.Headers.Add("Set-Cookie", "key1=value1; key2=value2; Path=/;");
request.Headers.Add("Another-Key", "value1");
request.Headers.Add("Set-Cookie", "key3=value3; Path=/;");
await client.SendAsync(request);
}
注意:它不必像示例中那样专门是
Set-Cookie
标头,它可以是任何重复的标头键。
但是在服务器端读取这些标头时,标头值显示为用逗号连接和分隔的不同值:
Set-Cookie:key1=value1; key2=value2; Path=/;, key3=value3; Path=/;
而且我特别希望服务器端接收一组值,所以应该是
"Set-Cookie": ["key1=value1; key2=value2; Path=/;","key3=value3; Path=/;"]
服务器端所需的行为可以通过 CURL 请求来实现:
curl --location 'http://localhost:8080/api/test' --header 'Set-Cookie: key1=value1; key2=value2; Path=/;' --header 'Another-Key: value1' --header 'Set-Cookie: key3=value3; Path=/;'
但是我无法为 .NET 请求标头复制这种类型的行为。我也尝试过使用
WebClient
和 HttpWebRequest
,但这两个都生成了单个逗号分隔的字符串。
有没有办法将具有不同值的多个相同键标头作为值数组发送,而不是发送多个值的单个连接字符串?
编辑:
对于服务器端测试,使用
IHttpContextAccessor
接口。它被注入到用于测试和读取标头的服务中。
var headers = _httpContextAccessor.HttpContext.Request.Headers;
问题是,出于生产目的,将使用第三方服务器,并且不能以任何方式对其进行修改,并且它特别需要相同密钥标头的值数组。
TL;DR:
HttpRequestMessage
和 HttpRequest
是不同的。
每当您创建
HttpClient
请求时,您都在使用 HttpRequestMessage
对象。
var req = new HttpRequestMessage(HttpMethod.Get, "http://test.com")
{
Headers =
{
{ "A", "A" },
{ "A", "B" }
}
};
上面的代码完全没问题,因为
Headers
属性定义为 HttpRequestHeaders
,它派生自 HttpHeaders
类:
public abstract class HttpHeaders : IEnumerable<KeyValuePair<string,IEnumerable<string>>>
如您所见,它被定义为一系列键值对,其中键是一个字符串,值是一系列字符串。
每当您访问
Request
的 HttpContext
时,您就不会使用 HttpRequestMessage
类型,而不是 HttpRequest
。
HttpRequest
的Headers
属性被定义为NameValueCollection
,它派生自NameObjectCollectionBase
类:
public abstract class NameObjectCollectionBase : ICollection, IDeserializationCallback, ISerializable
正如文档强调的那样
为关联的
键和String
值的集合提供抽象基类,可以使用键或索引访问Object
该值是单个对象,而不是一系列对象。因此,以下代码将产生
ArgumentException
(已添加具有相同键的项目):
var httpContext = new DefaultHttpContext();
httpContext.Request.Headers.Add("A", "A");
httpContext.Request.Headers.Add("A", "B");
为了支持同一键的多个值,微软只是将这些值用字符串连接起来。这也是你的实验所验证的。