首页 文章

在使用Web API自托管时,如何从HttpClientHandler.CookieContainer获取cookie?

提问于
浏览
2

我正在尝试为返回cookie的Web API方法编写集成测试 . 基于这个问题,我相信我需要设置HttpClientHandler的CookieContainer .

HttpClient Not Saving Cookies

然后,根据这个问题,我认为我需要将此HttpClientHandler设置为我的HttpServer实例的InnerHandler,以便我可以链接处理程序 .

How to perform in-memory test of HttpClientHandler

问题是我仍然发现CookieContainer是空的 . 我有一个Assert,它验证响应中是否有一个包含我期望的cookie的标头 . 这是我的代码:

// Set up in-memory hosting of Web API
        var config = new HttpConfiguration();
        WebApiConfig.Register(config);

        var cookieJar = new CookieContainer();
        var httpClientHandler = new HttpClientHandler
        {
            CookieContainer = cookieJar,
            UseCookies = true                
        };
        var httpServer = new HttpServer(config)
        {
            InnerHandler = httpClientHandler
        };

        const string loginUrl = "http://localhost/api/authentication/login";
        var uri = new Uri(loginUrl);

        var client = new HttpClient(httpServer) { BaseAddress = uri };

        var response =
            client.PostAsJsonAsync(uri,
                new LoginMessage {Email = UserEmail, Password = Password},
                CancellationToken.None).Result;
        response.EnsureSuccessStatusCode();

        var data = response.Content.ReadAsAsync<LoginResponse>().Result;
        Assert.IsTrue(response.Headers.Contains("Set-Cookie"));
        Assert.AreNotEqual(0, httpClientHandler.CookieContainer.Count);

关于CookieContainer中项目数的最后一个断言失败 . 我也试过调用 httpClientHandler.CookieContainer.GetCookies(uri) ,但生成的cookie集合仍然包含零元素 .

我也尝试明确链接我的客户端处理程序,但没有看到行为上的差异 .

var cookieJar = new CookieContainer();
        var httpClientHandler = new HttpClientHandler
        {
            CookieContainer = cookieJar,
            UseCookies = true
        };
        var httpServer = new HttpServer(config);

        var client = HttpClientFactory.Create(httpClientHandler, httpServer);

有人能告诉我在尝试检索这些cookie时我做错了什么吗?我在响应头中看到的cookie如下所示:

Temp=E4C4947BAB708D089C636B4A5BDA094A10C8B1D66347EBD96629CB9BDB589822198A09BCBBE22C13D07AFC4D4C3C91E78C08BECFC9CC03BEE881858A1B4752EDC1BB1E604B819FBAFE34776B6F46B78ADCD2421F8125A395784981BFF22CEBE19DB228158E85B5786279E55D4114B72E50098B2374C23A43B7C89EBA30F771C54E1D98A6B1CD315D1FB8623E8E97E41FE4279479B49D0A948E2752CA09BD17FF7B52764E96EA43DB9E98D7CEBD8A73C9547A696C170CFC9B6F75CA23B881ED9675C2344A2A16BEF2DFD70DBA723FB62578E7779ECADCF11347B22199DAC8FA6A; expires=Thu, 22 May 2014 01:37:36 GMT; path=/

1 回答

  • 3

    基于我在Darrel Miller的原始问题上收到的评论,看来处理这个问题的唯一方法是,如果我们有一个使用HttpServer作为内部处理程序的委托处理程序 .

    我最终构建了自己的CookieDelegateHandler,如下所示:

    public class CookieDelegateHandler : DelegatingHandler
        {
            public CookieContainer CookieContainer { get; set; }
            protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {
                return
                    base.SendAsync(request, cancellationToken).ContinueWith(responseToCompleteTask
                        =>
                    {
                        var result = responseToCompleteTask.Result;
                        var cookieHeaders = result.Headers.Where(pair => pair.Key == "Set-Cookie");
                        foreach (var value in cookieHeaders.SelectMany(header => header.Value))
                        {
                            CookieContainer.SetCookies(request.RequestUri, value);
                        }
                        return result;
                    }, TaskContinuationOptions.OnlyOnRanToCompletion);
            }
        }
    

    通过这个实现,我可以像这样实例化HttpClient:

    var client = new HttpClient(new CookieDelegateHandler
        {
            CookieContainer = new CookieContainer(),
            InnerHandler = new HttpServer(config)
        });
    

    执行委托处理程序的继续,并将cookie添加到CookieContainer .

    如果没有这个自定义委托处理程序,我欢迎任何其他关于如何解决这个问题的想法,或者对我的解决方案中是否存在问题进行评论 .

相关问题