-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Conversation
@@ -783,7 +783,7 @@ private void EnsureSessionHandleExists(WinHttpRequestState state) | |||
// Specify an HTTP server. | |||
connectHandle = Interop.WinHttp.WinHttpConnect( | |||
_sessionHandle, | |||
state.RequestMessage.RequestUri.Host, | |||
state.RequestMessage.RequestUri.HostNameType == UriHostNameType.IPv6 ? $"[{state.RequestMessage.RequestUri.IdnHost}]" : state.RequestMessage.RequestUri.IdnHost, |
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.
With regard to this i'm writing a manual test.
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.
@davidsh @rmkerr @Caesar1995 without []
ipv6 http://[::1234]:8080
and http://[::1234]
tests fails with ERROR_INTERNET_INVALID_URL
.
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.
@Caesar1995 related to https://github.com/dotnet/corefx/issues/28863#issue-311719169 if this PR will be merged i think we'll need to remove workaround also here.
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.
Yes, thanks for bringing this up! I will update that issue with this PR.
Assert.NotNull(ex.InnerException); | ||
|
||
//ERROR_INTERNET_INVALID_URL https://msdn.microsoft.com/en-us/library/windows/desktop/aa385465(v=vs.85).aspx | ||
Assert.NotEqual(12005, (int)ex.InnerException.GetType().GetProperty("NativeErrorCode").GetValue(ex.InnerException)); |
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 used reflection to avoid to add reference for WinHttpException
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.
You don't need to use reflection.
While WinHttpException
is not a public type, it is derived from Win32Exception
which is a public type. And the NativeErrorCode property can be accessed directly.
https://msdn.microsoft.com/en-us/library/system.componentmodel.win32exception(v=vs.110).aspx
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.
done
[InlineData("http://[::1234]:8080", false, null)] | ||
[InlineData("http://127.0.0.1", false, null)] | ||
[InlineData("http://www.microsoft.com", false, "www.microsoft.com")] | ||
public async Task ManualTest_IdnHostName(string requestUri, bool codeBase64, string requestHost) |
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.
@davidsh @rmkerr @Caesar1995 i tried to create a manual test, get back to me.
Take internationalized domain name 'Bangladesh' sample url from http://www.i18nguy.com/markup/idna-examples.html | ||
Saved in codeBase64 to avoid Visual Studio complains about encoding | ||
*/ | ||
[InlineData("aHR0cDovL+CmrOCmvuCmguCmsuCmvuCmpuCnh+Cmti5pY29tLm11c2V1bQ==", true, "icom.museum")] |
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 isn't necessary to use Base64 encoding to create Unicode Uri literals. Just use "\uuuu" notation in the literals.
i.e. "http://\u09AC\u09BE\u0982\u09B2\u09BE\u09A6\u09C7\u09B6.icom.museum"
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.
done
@dotnet-bot test Outerloop Linux x64 Debug Build please |
@Caesar1995 seems unrelated issue, right? |
[InlineData("http://[::1234]:8080", null)] | ||
[InlineData("http://127.0.0.1", null)] | ||
[InlineData("http://www.microsoft.com", "www.microsoft.com")] | ||
public async Task ManualTest_IdnHostName(string requestUri, string requestHost) |
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 think this manual test should be simplified. The only test we really need to add is an end-to-end test that validates that a request can be made to a server that uses Unicode characters in the DNS name. The other test cases are really already covered by other IPv4 and IPv6 literal test cases in System.Net.Http/tests/FunctionalTests.
Also, then, this test would be more valuable as a test case in the System.Net.Http/tests/FunctionalTests folder so that it can be run, manually, across the different handlers.
This test should also be marked in a way so that it doesn't get run all the time in CI because then it will be trying to connect all the time to a server that doesn't really exist.
The error handling then for HttpRequestException doesn't need to be present then since the test is only validating a successful operation when run.
Even better, would be if we could use a third-party server on the public Internet that uses Unicode characters in the DNS names. I'm sure that there are lots of them. Here is one that appears to be a international version of the Starbucks website.
Unicode: 스타벅스코리아.com
Punnycode: xn--oy2b35ckwhba574atvuzkc.com
\uuuu format: \uc2a4\ud0c0\ubc85\uc2a4\ucf54\ub9ac\uc544.com
So if you used that website, then the test could always be enabled and you would check for a successful connection.
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.
@davidsh ok i'll move test to System.Net.Http/tests/FunctionalTests with simple successful operation check.
This test should also be marked in a way so that it doesn't get run all the time in CI because then it will be trying to connect all the time to a server that doesn't really exist
Do you mean [Outerloop] or do you have some test sample to take a cue?
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.
If you use the website (international Starbucks) that I described above, then you can simply mark the test as [Outerloop]. It will still get run all the time during outerloop CI runs. By default, tests in CI only run innerloop.
However, if the website was something that can't normally be reached, then you would mark this test in some other way so that it never runs in innerloop nor outerloop.
I recommend you simply try to use the website I indicated and then the test can run in outerloop all the time.
string idn = "\uc2a4\ud0c0\ubc85\uc2a4\ucf54\ub9ac\uc544.com"; | ||
using (HttpResponseMessage response = await client.GetAsync("http://" + idn)) | ||
{ | ||
response.EnsureSuccessStatusCode(); |
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.
@davidsh i added response.EnsureSuccessStatusCode();
as assertion.
Question on tests, i want to understand how do we test all handlers, I've noticed that test run two times, one for every handler, how it works?
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.
In System.Net.Http.FunctionalTest
project, we have abstract base test class, that's where you want to your test. The current location System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs
is correct. Since the base class is abstract, those test cases will only be invoked by derived types (explained below).
There are two files which will actually invoke all the test cases. PlatformHandlerTest.cs
, which will run the test against platform specific handlers (WinHttpHandler on Windows, and CurlHandler on Unix), and SocketsHttpHandler
, which will run the test using our managed SocketsHttpHandler.
Even though you only modified the WinHttpHandler
's code, we want to make sure the test you added is not specific to WinHttpHandler
, and will pass with other handlers. To do so, you will help us detect/avoid platform specific behavior difference.
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.
@Caesar1995 understood TYVM!
@@ -1659,7 +1659,7 @@ public void GetAsync_ServerNeedsAuthAndNoCredential_StatusCodeUnauthorized() | |||
} | |||
}); | |||
} | |||
|
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 don't know why...in my vs diff tool these changes weren't visible, should i remove?
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.
Yes, please remove any changes that aren't part of the PR.
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.
done
@dotnet-bot test Outerloop Linux x64 Debug Build please |
string idn = "\uc2a4\ud0c0\ubc85\uc2a4\ucf54\ub9ac\uc544.com"; | ||
using (HttpResponseMessage response = await client.GetAsync("http://" + idn)) | ||
{ | ||
response.EnsureSuccessStatusCode(); |
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.
@davidsh i added response.EnsureSuccessStatusCode(); as assertion.
Question on tests, i want to understand how do we test all handlers, I've noticed that test run two times, one for every handler, how it works?
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.
Explained in one of the comments above.
@@ -2138,6 +2138,25 @@ public void GetAsync_ServerNeedsAuthAndNoCredential_StatusCodeUnauthorized() | |||
}); | |||
} | |||
|
|||
[OuterLoop] | |||
[Fact] | |||
public async Task GetAsync_IdnHostName() |
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.
Usually the naming for the test function should be like: A_B_C, A is the attribute what we are testing about, B is the condition to trigger the attribute, and C is the behavior outcome.
You can change to something like GetAsync_IdnHostName_SuccessStatusCodeInResponse
.
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.
done
/* | ||
international version of the Starbucks website | ||
Punnycode: xn--oy2b35ckwhba574atvuzkc.com | ||
*/ |
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.
In corefx, we usually do comment like this:
// Here is the 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.
done
@dotnet-bot test Outerloop Linux x64 Debug Build please |
HttpClientHandler handler = CreateHttpClientHandler(); | ||
using (var client = new HttpClient(handler)) | ||
{ | ||
//international version of the Starbucks website |
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.
Add space character after "//" comment characters.
{ | ||
//international version of the Starbucks website | ||
//punnycode: xn--oy2b35ckwhba574atvuzkc.com | ||
string idn = "\uc2a4\ud0c0\ubc85\uc2a4\ucf54\ub9ac\uc544.com"; |
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 would name this variable to something like "server". "idn" implies that this string consists of punnycode character which it doesn't. It is simply a hostname of a endpoint that just happens to have Unicode characters in the name.
And I would simplify this by bringing in the "http://" portion of the string here as well, i.e.
string server = "http://\uc2a4\ud0c0\ubc85\uc2a4\ucf54\ub9ac\uc544.com";
@@ -2138,6 +2138,23 @@ public void GetAsync_ServerNeedsAuthAndNoCredential_StatusCodeUnauthorized() | |||
}); | |||
} | |||
|
|||
[OuterLoop] | |||
[Fact] | |||
public async Task GetAsync_IdnHostName_SuccessStatusCodeInResponse() |
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 would change this name to: "GetAsync_UnicodeHostName_SuccessStatusCodeInResponse"
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.
Also, did you confirm that this test will fail without the fix in WinHttpHandler (to use IdnHost instead of Host)?
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.
actually no, i did only IdnHost square brackets tests. I'll do test.
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.
Note that WinHttp does not accept international host names without converting them first to Punycode
@davidsh...weird...seems to work, i tried also others url to test different characters...
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.
@davidsh...weird...seems to work, i tried also others url to test different characters...
Perhaps WinHTTP has changed behavior on recent Windows OS versions to allow Unicode characters to be used in the API calls. However, if you look at WireShark traces, you'll probably see IDN (punnycode) encoding actually used underneath. Did you observe that?
It's possible that the documentation is out of date and needs to be corrected. This needs to be researched. @Caesar1995 can you start an offline email with WinHTTP team and ask them about this behavior?
For now, it would be useful to update your PR to remove the product code change in WinHttpHandler but keep the new test you added. Then run all the tests against this PR and see what passes/fails. Perhaps older Windows OS versions like Windows 7 might fail. We need to understand this more. It's possible that we don't need a product code change at all but the new test is useful.
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 did a test with fiddler and i saw punycode going out, i'll restore WinHttpHandler...i apologize i assumed that guide was up to date, must never do.
@dotnet-bot test Outerloop Linux x64 Debug Build please |
@dotnet-bot test Outerloop Windows x64 Debug Build please |
@davidsh @Caesar1995 test fail on Windows.7.Amd64.Open-x64-Debug as you thought.
Maybe the guide is "conservative" for backward compatibility. |
@dotnet-bot test Outerloop Linux x64 Debug Build please |
@davidsh @Caesar1995 i don't see issue on Win7 for old test without fix(test fail) |
using (var client = new HttpClient(handler)) | ||
{ | ||
// international version of the Starbucks website | ||
// punnycode: xn--oy2b35ckwhba574atvuzkc.com |
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.
Nit: punnycode => punycode
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.
thank's
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.
Thanks for the PR!
@dotnet-bot Test Outerloop Windows x64 Debug Build |
CI failures in OSX x64 Debug Build are unrelated to PR. Will merge this once Outerloop Windows tests completes |
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.
Thanks for fixing this!
* pass IdnHost * add manual functional test * cleanup * fix comment * address PR feedback * address PR feedback * address PR feedback * address PR feedback * address PR feedback * address PR feedback * address PR feedback * fix IPv6 IdnHost * address PR feedback Commit migrated from dotnet/corefx@b2893f0
fixes #28722
replace PR #28818
cc: @davidsh @rmkerr @Caesar1995