【问题标题】:How to manage cookies with HttpClient when using a mocking HttpMessageHandler使用模拟 HttpMessageHandler 时如何使用 HttpClient 管理 cookie
【发布时间】:2013-03-23 14:59:17
【问题描述】:

我有一个单元测试,它通过传入HttpRequestMessage 实例并接收HttpResponseMessages 实例返回来调用类库。在这方面,它与测试 WebApi ApiController 非常相似。

我正在测试的代码将 cookie 添加到 HttpResponseMessage,并希望在随后传入的 HttpRequestMessage 调用中看到这些 cookie,这就是浏览器(或 HttpWebRequest)的行为方式。

我没有使用HttpClientHandler,因为请求实际上并没有在网络上进行,而是使用我初始化HttpClient 的模拟HttpMessageHandler 传递给产品。因此我无法访问HttpClientHandler 中的 cookie 处理。看来,要获得我需要的 cookie 行为,我将不得不手动解析 HttpResponseMessage 中的 cookie,然后手动将它们序列化为 HttpRequestMessage。这也完全忽略了 CookieContainer 将 cookie 正确应用于正确请求的逻辑。

有没有更简单的方法?

【问题讨论】:

    标签: mocking httpcookie dotnet-httpclient


    【解决方案1】:

    我写了自己的 DelegatingHandler 来为我管理 cookie。我还在CookieContainer 上写了几个扩展方法,以便与HttpRequestMessageHttpResponseMessage 一起使用:

    internal class DangerouslySimpleCookieContainer : DelegatingHandler {
        internal DangerouslySimpleCookieContainer(CookieContainer cookieContainer = null) {
            this.Container = cookieContainer ?? new CookieContainer();
        }
    
        internal DangerouslySimpleCookieContainer(HttpMessageHandler innerHandler, CookieContainer cookieContainer = null)
            : base(innerHandler) {
            this.Container = cookieContainer ?? new CookieContainer();
        }
    
        public CookieContainer Container { get; set; }
    
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) {
            this.Container.ApplyCookies(request);
            var response = await base.SendAsync(request, cancellationToken);
            this.Container.SetCookies(response);
            return response;
        }
    }
    
    internal static class CookieContainerExtensions {
        internal static void SetCookies(this CookieContainer container, HttpResponseMessage response, Uri requestUri = null) {
            Requires.NotNull(container, "container");
            Requires.NotNull(response, "response");
    
            IEnumerable<string> cookieHeaders;
            if (response.Headers.TryGetValues("Set-Cookie", out cookieHeaders)) {
                foreach (string cookie in cookieHeaders) {
                    container.SetCookies(requestUri ?? response.RequestMessage.RequestUri, cookie);
                }
            }
        }
    
        internal static void ApplyCookies(this CookieContainer container, HttpRequestMessage request) {
            Requires.NotNull(container, "container");
            Requires.NotNull(request, "request");
    
            string cookieHeader = container.GetCookieHeader(request.RequestUri);
            if (!string.IsNullOrEmpty(cookieHeader)) {
                request.Headers.TryAddWithoutValidation("Cookie", cookieHeader);
            }
        }
    }
    

    【讨论】:

    • 不错。我相信随着时间的推移,我们会想要替换目前在 HttpClientHandler 和 WebRequestHandler 中的一大堆功能。 (见en.wikipedia.org/wiki/HTTP_2.0
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    • 2020-05-10
    • 2021-04-01
    • 2012-02-22
    相关资源
    最近更新 更多