简体   繁体   English

如何将 HttpContext.Request/Response 的标头与 HttpRequestMessage.Request/Response 的标头进行比较?

[英]How do I compare headers from HttpContext.Request/Response with those of HttpRequestMessage.Request/Response?

I am annoyed with the HttpContext class that uses different types for the request and response than HttpRequestMessage and HttpResponseMessage .我对HttpContext class 使用与HttpRequestMessageHttpResponseMessage不同的请求和响应类型感到恼火。 The HttpContext class uses IHeaderDictionary for the headers while the other classes use HttpRequestHeaders and HttpResponseHeaders for the headers. HttpContext class 使用IHeaderDictionary作为标头,而其他类使用HttpRequestHeadersHttpResponseHeaders作为标头。 (Both are derived from HttpHeaders .) (两者都派生自HttpHeaders 。)
My problem is that I'm working on a Web API that needs to extract headers from the context and pass these headers onwards while using HttpClient.SendAsync(...) to call another site.我的问题是我正在处理 Web API 需要从上下文中提取标头并在使用HttpClient.SendAsync(...)调用另一个站点时向前传递这些标头。 (Yes, site! Not another service!) (是的,网站!不是其他服务!)
What I want is a simple function that can copy the headers from the context request to the new request.我想要的是一个简单的 function,它可以将标头从上下文请求复制到新请求。 And after the request is executed I want to use the same function to copy the headers from the response into my context response.在执行请求后,我想使用相同的 function将响应中的标头复制到我的上下文响应中。 This cannot be done because the headers are different types.这无法完成,因为标题是不同的类型。

The types involved are:涉及的类型有:
interface IHeaderDictionary: IDictionary<string, StringValues>{}
class HttpHeaders: IEnumerable<KeyValuePair<string, IEnumerable<string>>>
So the challenge is that we have a dictionary with a StringValues value versus an enumerable with an enumerable as value.所以挑战在于我们有一个带有StringValues值的字典与一个带有可枚举 as 值的可枚举。 Comparing apples and pears, basically...比较苹果和梨,基本上...
So how do I make a single function that can assign headers from one list to another?那么我如何制作一个可以将标题从一个列表分配给另一个列表的 function呢?

The best thing that I could come up with is partially DRY, and is mostly typesafe.我能想到的最好的事情是部分 DRY,并且大部分是类型安全的。

void Copy<T, U>(IEnumerable<KeyValuePair<string, T>> from, IEnumerable<KeyValuePair<string, U>> to)
    where T : IEnumerable<string>
    where U : IEnumerable<string>
{
    if (to is IHeaderDictionary headerDictionary)
        foreach (var x in from)
            headerDictionary.Add(x.Key, new StringValues(x.Value.ToArray()));
    else
    if (to is HttpHeaders httpHeaders)
        foreach (var x in from)
            httpHeaders.Add(x.Key, new List<string?>(x.Value));
}

This method assumes both collections actually already exist.此方法假定 collections 实际上已经存在。 If you have to create the target collection and return it, the method would get way more complex, and you'd lose the ability to infer the type parameters at the call site.如果您必须创建目标集合并返回它,该方法将变得更加复杂,并且您将失去在调用站点推断类型参数的能力。

To prove that the code can actually be compiled, I created a controller with a variation of Copy that takes nullable parameters.为了证明代码实际上可以编译,我创建了一个 controller,它带有一个采用可为空参数的Copy变体。 (This is just to keep all of it in a single place). (这只是为了将所有内容保存在一个地方)。

[ApiController]
public class WeatherForecastController : ControllerBase
{
    void Copy<T, U>(IEnumerable<KeyValuePair<string, T>>? from, IEnumerable<KeyValuePair<string, U>>? to)
        where T : IEnumerable<string>
        where U : IEnumerable<string>
    {
        if (from == null || to == null)
            return;

        if (to is IHeaderDictionary headerDictionary)
            foreach (var x in from)
                headerDictionary.Add(x.Key, new StringValues(x.Value.ToArray()));
        else
        if (to is HttpHeaders httpHeaders)
            foreach (var x in from)
                httpHeaders.Add(x.Key, new List<string?>(x.Value));
    }

    public void Test()
    {
        // in real life, these come from somewhere else and won't be null
        HttpRequestHeaders? requestHeaders = null;
        HttpRequestHeaders? responseHeaders = null;

        // actual types are inferred. yay!
        Copy(HttpContext.Request.Headers, requestHeaders);
        Copy(requestHeaders, HttpContext.Request.Headers);
        Copy(HttpContext.Response.Headers, responseHeaders);
        Copy(responseHeaders, HttpContext.Response.Headers);
        Copy(requestHeaders, responseHeaders);
        Copy(responseHeaders, requestHeaders);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM