Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System.Net.Http.HttpClientHandler.CookieContainer is empty in a UWP app when cookies are set on 302 redirect response #17466

Closed
pphadke-zz opened this issue May 31, 2016 · 6 comments
Assignees
Milestone

Comments

@pphadke-zz
Copy link

When the System.Net.Http.HttpClient class - with a HttpClientHandler is used from a UWP, the response cookie collection returned is empty. This happens when the cookies are being set on a 302 redirect response.

When you collect a network trace, you should notice the below request/response pattern:

Request:

GET location HTTP/1.1
Host: host
Connection: Keep-Alive
...other request headers

Response:

HTTP/1.1 302 Object moved
Set-Cookie: name=value;
Location: redirect location
...other response headers

The problem happens because the default behavior of the HttpClientHandler is to perform auto-redirection. With this setting, the .NET layer does not get to see the cookies in the redirect response leading to the buggy behavior.

@davidsh davidsh self-assigned this May 31, 2016
@pphadke-zz
Copy link
Author

To workaround this issue, you can use either of the two approaches:

1.) You can continue to use the System.Net.Http.HttpClient class, but then you also have to turn off the default auto-redirection property of the HttpClientHandler (HttpClientHandler.AllowAutoRedirect = false) and perform the redirection manually (instead of automatically). When you do this, the HTTP 302 response you receive should populate the Cookie collection correctly.

2.) Use the WinRT Windows.Web.Http.HttpClient class to handle this scenario. Typically, you will use code similar to this:

    private async void buttonWWH_Click(object sender, RoutedEventArgs e)
    {
        Windows.Web.Http.Filters.HttpBaseProtocolFilter filter = new Windows.Web.Http.Filters.HttpBaseProtocolFilter();
        Windows.Web.Http.HttpClient http = new Windows.Web.Http.HttpClient(filter);
        var req = new Windows.Web.Http.HttpRequestMessage(Windows.Web.Http.HttpMethod.Get, new Uri(txtUri.Text));

        var result = await http.SendRequestAsync(req);
        // consume the response
        var responseText = result.StatusCode.ToString() + await result.Content.ReadAsStringAsync();

        // get the cookies of the request that elicited this response and display
        var responseCookies = filter.CookieManager.GetCookies(result.RequestMessage.RequestUri).Cast<Windows.Web.Http.HttpCookie>().ToArray();

        string cookiesString = "";
        for (int i = 0; i < responseCookies.Length; i++)
        {
            cookiesString = cookiesString + responseCookies[i].Name + "=" + responseCookies[i].Value + Environment.NewLine;
        }
        // check to see the response cookies
        var responseCookies = cookiesString == ""? "Cookie collection is empty.": cookiesString;
    }

@pphadke-zz pphadke-zz reopened this May 31, 2016
@davidsh davidsh removed their assignment Nov 18, 2016
@GeertvanHorrik
Copy link
Contributor

This is exactly what I encountered today with the latest System.Net.Http (4.1.0. I think). It happens in a UWP app. I guess the issue is that the Location header is handled before parsing the cookie.

As @pphadke explains, the workaround is:

  1. Create a separate HttpClient with a custom HttpClientHandler, set EnableAutoRedirect to true
  2. Request the site you wish to retrieve all cookies for and make sure to check for the Location header since you need to redirect yourself (until the Location header is null).
    3. Then create a secondary (final) HttpClientHandler and set the CookieContainer to be the instance of the first HttpClientHandler.
  3. Finally create a new HttpClient, this contains all the cookies and you can start using the final HttpClient and it deals with cookies the same way as a browser does.

huming2207 referenced this issue in huming2207/Rmiter Mar 6, 2017
For the (most possible) reason why it crashes, see: https://github.com/dotnet/corefx/issues/9003
Anyway I need to rewrite RmitCoreUwp library's HTTP handling stuff.
huming2207 referenced this issue in huming2207/Rmiter Mar 7, 2017
Added` a tricky workaround, microsoft made a weird bug on System.Net.Http
library. The library will become an idiot and refuse to handle the
cookies well when 302 Redirection occurs. Meanwhile, it seems that
Microsoft forgot (or ignored? rejected?) to fix this as the bug has been
found long ago.
(see: https://github.com/dotnet/corefx/issues/9003)
@ghost
Copy link

ghost commented May 18, 2017

Has this been fixed?

@davidsh
Copy link
Contributor

davidsh commented May 18, 2017

Has this been fixed?

It has not been fixed yet. The fix would be part of our UAP/UWP work for .NET Core 2.1 release.

@Petermarcu Petermarcu assigned Petermarcu and DavidGoll and unassigned Petermarcu Jun 15, 2017
@davidsh davidsh assigned davidsh and unassigned DavidGoll Jun 20, 2017
@ghost
Copy link

ghost commented Jul 3, 2017

By the way, this doesn't just affect windows UWP apps, this is broken on macOS and Xamarin.Forms with PCL

@davidsh
Copy link
Contributor

davidsh commented Jul 3, 2017

By the way, this doesn't just affect windows UWP apps, this is broken on macOS and Xamarin.Forms with PCL

cc: @stephentoub

davidsh referenced this issue in dotnet/corefx Jul 28, 2017
* Fix HttpClient redirection logic on UAP

This PR changes the implementation of sending requests in HttpClient for UAP when
dealing with redirection. In the past, we would let the WinRT layer handle auto
redirection logic. However, due to #9003, the cookies were getting lost on 3xx responses
since the .NET layer didn't see them. So, this PR implements the redirection ourselves.

One important part of redirection is that we need to drop credentials. The WinRT layer
did this for us. However, we are unable to use a single WinRT HttpBaseProtocolFilter object
since we need to remove the credential after the first redirect. So, we need to maintain
a second filter that uses no credentials and keep it in sync regarding all the other properties
of the primary filter.

With this PR, the behavior of other aspects (such as controlling max number of redirects, etc.)
now matches .NET Framework.  So, some tests were adjusted to remove the UAP specific behavior
checks.

Fixes #9003
Fixes #22191

* Disable test on Linux

* Address PR feedback

* Disable failing HTTP/2 test
@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the UWP6.0 milestone Jan 31, 2020
@dotnet dotnet locked as resolved and limited conversation to collaborators Dec 31, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants