-
Notifications
You must be signed in to change notification settings - Fork 507
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
[NSUrlSessionHandler] Only update the request's RequestUri if a redirection occurred. Fixes #20629. #20633
[NSUrlSessionHandler] Only update the request's RequestUri if a redirection occurred. Fixes #20629. #20633
Conversation
…ection occurred. Fixes xamarin#20629. The logic to update the request's RequestUri is somewhat old: xamarin/ModernHttpClient@518ac1b but it makes sense to do so. Some testing with a console app, also revealed that a plain .NET does this in case of a redirect: ```cs async static Task Main () { var client = new HttpClient () { BaseAddress = new Uri("https://httpbin.org") }; var request = new HttpRequestMessage (HttpMethod.Get, "/redirect-to?url=https%3A%2F%2Fmicrosoft.com&status_code=302&queries[]={}" ); Console.WriteLine ($"Request uri 1: {request.RequestUri}"); var response = await client.SendAsync(request); Console.WriteLine ($"Request uri 2: {request.RequestUri}"); var content = await response.Content.ReadAsStringAsync(); Console.WriteLine ((int) response.StatusCode); Console.WriteLine(content.Length); } ``` prints: ``` Request uri 1: /redirect-to?url=https%3A%2F%2Fmicrosoft.com&status_code=302&queries[]={} Request uri 2: https://www.microsoft.com/es-es/ 200 201252 ``` Further looking into .NET's code, `SocketsHttpHandler` updates RequestUri after following a redirect: https://github.com/dotnet/runtime/blob/f5eb26e4da0d0d7a5874553d8a793a551c34af0a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/RedirectHandler.cs#L65-L66 So it seems the expected behavior is to update RequestUri only in case of a redirect. Now the question becomes: how to detect whether we're a redirect or not? Contrary to `SocketsHttpHandler`, we don't do the actual redirect, it's handled transparently by `NSUrlSession`. Fortunately `NSUrlSessionTask` has two properties which help: [`OriginalRequest`][1] and [`CurrentRequest`][2]. According to Apple's documentation, these are the same, "except when the server has responded to the initial request with a redirect to a different URL." This sounds perfect for us, so use these two properties to determine whether a redirect occurred. Note that we can't use object identity, because these are 'copy' properties, which means they'll never be the same instances, only at most a copy of eachother. So instead compare the `AbsoluteString` property to check for equality. As far as I'm aware, none of the other properties (request body, headers, cookies, etc.) can be set by the server in a redirect, so there's no need to compare those. Fixes xamarin#20629. [1]: https://developer.apple.com/documentation/foundation/nsurlsessiontask/1411572-originalrequest [2]: https://developer.apple.com/documentation/foundation/nsurlsessiontask/1411649-currentrequest
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…pdate-requesturi-if-redirected
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…pdate-requesturi-if-redirected
📚 [PR Build] Artifacts 📚Packages generatedView packagesPipeline on Agent |
💻 [PR Build] Tests on macOS X64 - Mac Sonoma (14) passed 💻✅ All tests on macOS X64 - Mac Sonoma (14) passed. Pipeline on Agent |
💻 [PR Build] Tests on macOS M1 - Mac Ventura (13) passed 💻✅ All tests on macOS M1 - Mac Ventura (13) passed. Pipeline on Agent |
💻 [PR Build] Tests on macOS M1 - Mac Monterey (12) passed 💻✅ All tests on macOS M1 - Mac Monterey (12) passed. Pipeline on Agent |
💻 [CI Build] Windows Integration Tests passed 💻✅ All Windows Integration Tests passed. Pipeline on Agent |
💻 [PR Build] Tests on macOS M1 - Mac Big Sur (11) passed 💻✅ All tests on macOS M1 - Mac Big Sur (11) passed. Pipeline on Agent |
✅ API diff for current PR / commitLegacy Xamarin (No breaking changes)
NET (empty diffs)
✅ API diff vs stableLegacy Xamarin (No breaking changes).NET (No breaking changes)ℹ️ Generator diffGenerator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes) Pipeline on Agent |
This comment has been minimized.
This comment has been minimized.
🚀 [CI Build] Test results 🚀Test results✅ All tests passed on VSTS: test results. 🎉 All 170 tests passed 🎉 Tests counts✅ cecil: All 1 tests passed. Html Report (VSDrops) Download Pipeline on Agent |
The logic to update the request's RequestUri is somewhat old:
xamarin/ModernHttpClient@518ac1b
but it makes sense to do so.
Some testing with a console app, also revealed that a plain .NET does this in
case of a redirect:
prints:
Further looking into .NET's code,
SocketsHttpHandler
updates RequestUri afterfollowing a redirect:
https://github.com/dotnet/runtime/blob/f5eb26e4da0d0d7a5874553d8a793a551c34af0a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/RedirectHandler.cs#L65-L66
So it seems the expected behavior is to update RequestUri only in case of a
redirect.
Now the question becomes: how to detect whether we're a redirect or not?
Contrary to
SocketsHttpHandler
, we don't do the actual redirect, it'shandled transparently by
NSUrlSession
.Fortunately
NSUrlSessionTask
has two properties which help:OriginalRequest
andCurrentRequest
. According to Apple'sdocumentation, these are the same, "except when the server has responded to
the initial request with a redirect to a different URL."
This sounds perfect for us, so use these two properties to determine whether a redirect occurred.
Note that we can't use object identity, because these are 'copy' properties,
which means they'll never be the same instances, only at most a copy of
eachother. So instead compare the
AbsoluteString
property to check forequality. As far as I'm aware, none of the other properties (request body,
headers, cookies, etc.) can be set by the server in a redirect, so there's no
need to compare those.
Fixes #20629.