从 Flurl.Http v2.0.1 中的请求取回 cookie

Getting back cookies from the request in Flurl.Http v2.0.1

使用 Flurl.Http v1.2 时,我们有以下代码:

1. var cookieJar = new CookieContainer();
2. var url = baseUrl.AppendPathSegment("api/auth/login");
3. var client = url.EnableCookies();
4. ((HttpClientHandler)client.HttpMessageHandler).CookieContainer = cookieJar;
5. var result = await client.PostJsonAsync(new { UserName = userName, Password = password });
6. var cookies = cookieJar.GetCookies(new Uri(baseUrl));
7. _cookie = cookies[0];

升级到 v2.0.1 后,第 4 行不再编译,因为 client 不再是 IFlurlClient,现在是 IFlurlRequest,根据发行说明。

我注意到 IFlurlRequest 有一个 Client 属性,所以我将第 4 行更改为:

4. ((HttpClientHandler)client.Client.HttpMessageHandler).CookieContainer = cookieJar;

现在编译但在 运行 时失败并出现 InvalidOperationException:

This instance has already started one or more requests. Properties can only be modified before sending the first request.

我假设这是因为对底层 HttpClient 的积极重用。我在 3 和 4 之间添加了一行,每次都创建一个新的 FlurlClient,以确保该实例无法启动请求。

1. var cookieJar = new CookieContainer();
2. var url = baseUrl.AppendPathSegment("api/auth/login");
3. var request = url.EnableCookies();
3.5 request.Client = new FlurlClient();
4. ((HttpClientHandler)request.Client.HttpMessageHandler).CookieContainer = cookieJar;
5. var result = client.PostJsonAsync(new { UserName = userName, Password = password }).Result;
6. var cookies = cookieJar.GetCookies(new Uri(baseUrl));
7. _cookie = cookies[0];

这现在又可以工作了,但我不确定我这样做的方式是否正确。如有任何反馈,我们将不胜感激。

您不需要显式管理 CookieContainer; Flurl 使使用 cookie 变得更加简单。

通常你希望尽可能多地重用 HttpClient 实例,当你没有显式创建 FlurlClient 时,2.0 会默认为你这样做,但在持久化的情况下多个调用中的 cookie 您可能想要自己管理 FlurlClient,否则多个线程可能是同一集合上的 reading/writing 个 cookie。

还是很简单的。我认为您的整个示例可以简化为:

using (var cli = new FlurlClient(baseUrl).EnableCookies()) {
    await cli.Request("api/auth/login").PostJsonAsync(new {
        UserName = userName,
        Password = password });
    _cookie = cli.Cookies.First().Value;
}