Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c#

flurl

When using Flurl.Http v1.2 we had the following code:

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];

After upgrading to v2.0.1 line 4 no longer compiles because client is no longer an IFlurlClient it's now an IFlurlRequest, as per the release notes.

I noticed that IFlurlRequest has a Client property, so I changed line 4 to be:

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

That now compiles but fails at run-time with an InvalidOperationException:

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

I'm assuming that's because of the aggressive reuse of the underlying HttpClient. I added a line between 3 and 4 to create a new FlurlClient each time to ensure the instance could not have started a request.

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];

This now works again, but I'm not sure I'm doing this the correct way. Any feedback would be appreciated.

like image 471
Craig W. Avatar asked Nov 14 '17 17:11

Craig W.


1 Answers

You shouldn't need to manage CookieContainer explicitly; Flurl makes working with cookies a lot simpler.

Generally you want to reuse HttpClient instances as much as possible, and 2.0 does do this for you by default when you don't create FlurlClients explicitly, but in the case of persisting cookies over multiple calls you're probably going to want to manage FlurlClient yourself, otherwise multiple threads could be reading/writing cookies on the same collection.

Still pretty easy. I think your whole example can be reduced to this:

using (var cli = new FlurlClient(baseUrl).EnableCookies()) {
    await cli.Request("api/auth/login").PostJsonAsync(new {
        UserName = userName,
        Password = password });
    _cookie = cli.Cookies.First().Value;
}
like image 108
Todd Menier Avatar answered Oct 23 '22 22:10

Todd Menier