-
Notifications
You must be signed in to change notification settings - Fork 549
[Foundation] Add CookieContainer support in NSUrlSessionHandler. #7654
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
[Foundation] Add CookieContainer support in NSUrlSessionHandler. #7654
Conversation
There are two important things to look at this: 1. That we do set the cookies that are present in the CookieContainer in the request. That is, we need to set Cookie headers for all of them. 2. That if we receive a Set-Cookie from the server, the CookieContainer gets correctly updated else we will have issues since we do not respect the data sent from the server side. Tests show both that we are setting the Cookie header and that we honour the Set-Cookie header. Fixes: dotnet#5665
|
Build failure Test results1 tests failed, 86 tests passed.Failed tests
|
chamons
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love the test. I think you left in debug spam.
| { | ||
| var uri = new Uri (url.AbsoluteString); | ||
| if (sessionHandler.cookieContainer != null && cookies.Length > 0) | ||
| lock (sessionHandler.inflightRequestsLock) { // esure we lock when writing to the collection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: type eNsure
spouliot
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
after CWL are removed
| if (cookies != null && cookies.Count > 0) { | ||
| foreach (var cookie in cookies) { | ||
| Console.WriteLine ($"Adding cookie: {cookie.ToString ()} "); | ||
| request.Headers.TryAddWithoutValidation (Cookie, cookie.ToString ()); // as per docs: Returns a string representation of this Cookie object that is suitable for including in a HTTP Cookie: request header. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure the standard allows having multiple Cookie headers.
I think the recommendation is to "join" all cookies into a single Cookie header using the ; character.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might want to use GetCookieHeader instead of GetCookies.
It looks that this is the approach that AndroidClientHandler.cs takes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a very good point. And I won't have to deal with the specific Header details!
| } | ||
| } | ||
|
|
||
| public CookieContainer CookieContainer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AndroidClientHandler.cs also has a UseCookies property inherited from HttpClientHandler. Interestingly enough, NSUrlSessionHandler inherits from HttpMessageHandler instead :-?
I'd say the property is useful since it allows you to opt-out from this feature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can implement such a property BUT we should do it in a diff PR. The issue is that we also have to deal with the fact that iOS has its own 'CookieContainer' so if we set the property, we have to make sure that we do not use the native CookieContainer or the managed one. I'd like to keep the PR small since this code is complicated. Added an issue that I'll fix once we land this: #7659
1. Remove poor mans debugger CWL. 2. Fix manuel typos. 3. Get the cookies header directly from the cookie container. Less looping and easier code.
| Assert.IsNull (ex, "Exception"); | ||
| Assert.IsNotNull (managedCookieResult, "Managed cookies result"); | ||
| Assert.IsNotNull (nativeCookieResult, "Native cookies result"); | ||
| Assert.AreEqual (managedCookieResult, nativeCookieResult, "Cookies"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My two cents - we should have an assertion on the generated NSUrlRequest that verifies the cookie header (name and value). This could be done by injecting the underlying NSUrlSession and capturing the parameter passed to CreateDataTask
Not sure if the current structure of the code allows this verification.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or better yet - this test might be a better candidate for an integration test that uses some sort of test server - either in process (e.g. https://github.com/WireMock-Net/WireMock.Net) or a live server (e.g. https://httpbin.org/get)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test is ensuring that the same cookies are sent when using the managed handler and the unmanaged. The request from httpbin.org returns a dictionary of cookies + values. So if they are equal, we should be fine.
| Assert.IsNotNull (nativeCookieResult, "Native cookies result"); | ||
| var cookiesFromServer = cookieContainer.GetCookies (new Uri (url)); | ||
| Assert.AreEqual (1, cookiesFromServer.Count, "Cookies received from server."); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would worth checking the name and the value of the actual cookie as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Valid point. Merge and will update the test :)
|
Build failure |
|
Build failure Test results1 tests failed, 86 tests passed.Failed tests
|
There are two important things to look at this:
the request. That is, we need to set Cookie headers for all of them.
gets correctly updated else we will have issues since we do not respect
the data sent from the server side.
Tests show both that we are setting the Cookie header and that we honour
the Set-Cookie header.
Fixes: #5665