Fix Uri.Host for IPv6 Link-local address#29829
Fix Uri.Host for IPv6 Link-local address#29829davidsh merged 10 commits intodotnet:masterfrom MarcoRossignoli:ipv6lla
Conversation
|
@dotnet-bot test Outerloop Linux x64 Release Build please |
| { | ||
| flags |= Flags.LoopbackHost; | ||
| } | ||
| if(linkLocalAddress) |
| if(linkLocalAddress) | ||
| { | ||
| flags |= Flags.LinkLocalAddress; | ||
| } |
There was a problem hiding this comment.
add newline after closing brace
| [Fact] | ||
| public void IdnDnsSafeHost_IPv6HostLinkLocalAddress_ScopeIdButNoBrackets() | ||
| { | ||
| Uri test = new Uri("http://[fe80::e077:c9a3:eeba:b8e9%18]/"); |
There was a problem hiding this comment.
You should refactor this duplicated string, "fe80::e077:c9a3:eeba:b8e9%18" into a constant in this test.
There was a problem hiding this comment.
i copied the pattern from test above https://github.com/MarcoRossignoli/corefx/blob/2d9eddafdf568afab7a8bb730415bfce9b885a15/src/System.Private.Uri/tests/FunctionalTests/IdnDnsSafeHostTest.cs#L41 do you confirm this refactoring?
There was a problem hiding this comment.
i copied the pattern from test above https://github.com/MarcoRossignoli/corefx/blob/2d9eddafdf568afab7a8bb730415bfce9b885a15/src/System.Private.Uri/tests/FunctionalTests/IdnDnsSafeHostTest.cs#L41 do you confirm this refactoring?
Following existing code and test patterns can be useful. But it doesn't work in all cases. Sometimes there are bad patterns in the code. And we don't change them all, but try to add better code for new PRs. Also, the pattern you cited uses simpler IP literals. This test uses a long IPv6 literal. So, for code cleanliness and ease of maintenance, it's better to consolidate if possible.
There was a problem hiding this comment.
done with [Theory] could be useful for future new data, if you like.
|
@dotnet-bot test Outerloop Linux x64 Release Build please |
| flags |= Flags.LoopbackHost; | ||
| } | ||
| if(linkLocalAddress) | ||
| } |
There was a problem hiding this comment.
There seems to be extra whitespace (space or tabs) after this closing brace.
|
@dotnet-bot test Outerloop Linux x64 Release Build please, on my Ubuntu 18.04 outerloop works well, i want to understand if the issue is related to SO version. |
|
@dotnet-bot test Linux x64 Release Build please |
|
@dotnet-bot test Outerloop Linux x64 Release Build please |
|
GetAsync_IPv6LinkLocalAddressUri_Success is failing with this change with CurlHandler on several distros: |
@stephentoub i need to setup an Ubuntu 14.04, i think depends on SO version(on my 18.04 it's ok, also on CI), let me try! EDIT(22/5): i repro issue with Ubuntu 14.04, i think depends on curl version, i'm checking fix/releases |
|
@dotnet-bot test Windows x64 Debug Build |
|
UPDATE: after some research i discovered that there is a difference in ipv6 parsing between curl versions, this PR change the way of parsing Fixed in 7.37.0 - May 21 2014 Ubuntu 14.04 use curl ver 7.35.0( |
|
@dotnet-bot test Outerloop Linux x64 Release Build please |
| string url = requestUri.Host == idnHost ? | ||
| requestUri.AbsoluteUri : | ||
| new UriBuilder(requestUri) { Host = idnHost }.Uri.AbsoluteUri; | ||
| string url = requestUri.Host == idnHost ? |
There was a problem hiding this comment.
As long as the tests would catch that break, I think the change is probably okay. The fix to add brackets on idnHost is risky enough that it will require more investigation.
| long scopeId; | ||
| if (IsLinkLocal(requestUri, out scopeId)) | ||
| bool isLinkLocal = false; | ||
| if ((isLinkLocal = IsLinkLocal(requestUri, out scopeId))) |
| new UriBuilder(requestUri) { Host = idnHost }.Uri.AbsoluteUri; | ||
| string url = requestUri.Host == idnHost ? | ||
| requestUri.AbsoluteUri : | ||
| new UriBuilder(requestUri){ Host = isLinkLocal && (scopeIdIndex = idnHost.IndexOf("%", StringComparison.OrdinalIgnoreCase)) != -1 ? idnHost.Substring(0, scopeIdIndex) : idnHost}.Uri.AbsoluteUri; |
There was a problem hiding this comment.
The IndexOf can just be idnHost.IndexOf('%')
| isLoopback = Parse(str, numbers, start, ref scopeId); | ||
| return '[' + CreateCanonicalName(numbers) + ']'; | ||
| linkLocalAddress = numbers[0] == 0xfe80; | ||
| return '[' + CreateCanonicalName(numbers) + (linkLocalAddress ? scopeId : "") + ']'; |
There was a problem hiding this comment.
Nit: the compiler will help fix this up, but it'd be better to use "[" and "]" rather than '[' and ']'.
There was a problem hiding this comment.
enlighten me...why?
There was a problem hiding this comment.
Because we want this to compile down to the efficient string.Concat(string, string, string, string) call. If the compiler didn't help here, this would end up being a call to string.Concat(params object[] args), which would result in an object[] allocation, the chars getting boxed (so two more allocations), and then having ToString called on them (so two more allocations), plus having a string array allocated in the Concat implementation to store the ToString on each input. As of dotnet/roslyn#415, the C# compiler should do the conversion from e.g. '[' to "[" for you, but why make it.
There was a problem hiding this comment.
understood TYVM!
| { | ||
| flags |= Flags.LoopbackHost; | ||
| } | ||
| if (linkLocalAddress) |
There was a problem hiding this comment.
add newline above this 'if' statement.
| [Theory] | ||
| [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] | ||
| [InlineData("fe80::e077:c9a3:eeba:b8e9", "%18")] | ||
| public void IdnDnsSafeHost_IPv6HostLinkLocalAddress_ScopeIdButNoBrackets(string address, string zoneIndex) |
There was a problem hiding this comment.
"ScopeIdButNoBrackets" part of the test name isn't quite right since there is an Assert in this test that validates for brackets.
Normally we don't have a single test method that test multiple properties. But I see that there is already other tests that do this in this file.
I suggest, though, that you rename the test like this:
"IdnDnsSafeHost_IPv6HostLinkLocalAddress_ScopeIdCorrectlyFormatted"
| [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] | ||
| public void Host_IPv6LinkLocalAddress_HasScopeId(string address, string zoneIndex) | ||
| { | ||
| string scopedLiteralIpv6 = "[" + address + zoneIndex + "]"; |
There was a problem hiding this comment.
"scopedLiteralIpv6" -> "scopedLiteralIpv6Brackets" to be more consistent with variable naming in the tests above.
| [InlineData("fe81::e077:c9a3:eeba:b8e9", "%18")] | ||
| public void Host_NonIPv6LinkLocalAddress_NoScopeId(string address, string zoneIndex) | ||
| { | ||
| string scopedLiteralIpv6 = "[" + address + zoneIndex + "]"; |
There was a problem hiding this comment.
"scopedLiteralIpv6" -> "scopedLiteralIpv6Brackets" to be more consistent with variable naming in the tests above.
|
@dotnet-bot test Outerloop Linux x64 Release Build please |
| Assert.Equal("[::1]", test.Host); | ||
| } | ||
|
|
||
| [Theory] |
There was a problem hiding this comment.
We usually use [Theory] for multiple test data. So here
- you can add more test data (
[InlineData]) - or use
[Fact], without taking any parameters, and create a constant in the test. As David mentioned here.
|
@dotnet-bot test this please @dotnet-bot test Outerloop Windows x64 Debug Build |
|
@dotnet-bot test Outerloop Windows x64 Debug Build |
| { | ||
| string address = "fe80::e077:c9a3:eeba:b8e9"; | ||
| string zoneIndex = "%18"; | ||
|
|
There was a problem hiding this comment.
Use
const string ScopedLiteralIpv6 = "fe80::e077:c9a3:eeba:b8e9%18"; since address and zoneIndex is not used anywhere else in the test.
There was a problem hiding this comment.
oh yes i missed it sorry
There was a problem hiding this comment.
done, updated also other test with constants.
|
@dotnet-bot test Outerloop Windows x64 Debug Build |
|
LGTM once CI is green. |
|
@dotnet-bot test Outerloop Windows x64 Debug Build |
1 similar comment
|
@dotnet-bot test Outerloop Windows x64 Debug Build |
caesar-chen
left a comment
There was a problem hiding this comment.
LGTM.
@dotnet/ncl Any additional feedback?
| { | ||
| ret = ret.Substring(1, ret.Length - 2); | ||
| if ((object)_info.ScopeId != null) | ||
| if ((object)_info.ScopeId != null && (_flags & Flags.IPv6LinkLocalAddress) == 0) |
There was a problem hiding this comment.
Nit: We can add a comment here to explain the purpose for the new flag. i,e,. to avoid duplicated ScopeId.
There was a problem hiding this comment.
Added, with new line before for readability, let me know if it's ok.
|
@dotnet-bot test Outerloop Windows x64 Debug Build |
rmkerr
left a comment
There was a problem hiding this comment.
This looks like a solid, well scoped change to me. It's unfortunate that we have to special case the behavior on Curl, but I think that the change you made there is correct. Pending approval from either @davidsh or @stephentoub, this looks good to me.
This reverts commit f7a8cf1.
Contributes to dotnet/corefx#28863 Replace PR dotnet/corefx#29769 after revert dotnet/corefx#29818 for Outerloop CI fail This PR address the second part of issue: Uri.Host LLA (Link-local address) IPv6 address doesn't contain %number part. Currently it returns [fe80::e077:c9a3:eeba:b8e9], it should return [fe80::e077:c9a3:eeba:b8e9%18]. Note: Uri.IdnHost correctly contains the %number part. Commit migrated from dotnet/corefx@f7a8cf1
…" (dotnet/corefx#30062) This reverts commit dotnet/corefx@f7a8cf1. Commit migrated from dotnet/corefx@e5bb0b5
contributes to #28863
replace PR #29769 after revert #29818 for Outerloop CI fail
this PR address the second part of issue:
Uri.HostLLA (Link-local address) IPv6 address doesn't contain%numberpart.[fe80::e077:c9a3:eeba:b8e9], it should return[fe80::e077:c9a3:eeba:b8e9%18].Uri.IdnHostcorrectly contains the%numberpart.cc: @rmkerr @Caesar1995 @davidsh @stephentoub