Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corefx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs7
-rw-r--r--src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPoolManager.cs15
-rw-r--r--src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs61
3 files changed, 77 insertions, 6 deletions
diff --git a/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs b/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs
index 8a590a4777..d2e8c02b04 100644
--- a/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs
+++ b/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs
@@ -294,7 +294,12 @@ namespace System.Net.Http
else
{
Debug.Assert(_pool.UsingProxy);
- await WriteAsciiStringAsync(uri.IdnHost).ConfigureAwait(false);
+
+ // If the hostname is an IPv6 address, uri.IdnHost will return the address without enclosing [].
+ // In this case, use uri.Host instead, which will correctly enclose with [].
+ // Note we don't need punycode encoding if it's an IP address, so using uri.Host is fine.
+ await WriteAsciiStringAsync(uri.HostNameType == UriHostNameType.IPv6 ?
+ uri.Host : uri.IdnHost).ConfigureAwait(false);
if (!uri.IsDefaultPort)
{
diff --git a/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPoolManager.cs b/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPoolManager.cs
index df1f4f50ad..73d87d9d46 100644
--- a/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPoolManager.cs
+++ b/src/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnectionPoolManager.cs
@@ -148,10 +148,15 @@ namespace System.Net.Http
{
Uri uri = request.RequestUri;
+ // If the hostname is an IPv6 address, uri.IdnHost will return the address without enclosing [].
+ // In this case, use uri.Host instead, which will correctly enclose with [].
+ // Note we don't need punycode encoding if it's an IP address, so using uri.Host is fine.
+ bool isIPv6Address = uri.HostNameType == UriHostNameType.IPv6;
+
if (isProxyConnect)
{
Debug.Assert(uri == proxyUri);
- return new HttpConnectionKey(HttpConnectionKind.ProxyConnect, uri.IdnHost, uri.Port, null, proxyUri);
+ return new HttpConnectionKey(HttpConnectionKind.ProxyConnect, isIPv6Address ? uri.Host : uri.IdnHost, uri.Port, null, proxyUri);
}
string sslHostName = null;
@@ -177,7 +182,7 @@ namespace System.Net.Http
if (HttpUtilities.IsNonSecureWebSocketScheme(uri.Scheme))
{
// Non-secure websocket connection through proxy to the destination.
- return new HttpConnectionKey(HttpConnectionKind.ProxyTunnel, uri.IdnHost, uri.Port, null, proxyUri);
+ return new HttpConnectionKey(HttpConnectionKind.ProxyTunnel, isIPv6Address ? uri.Host : uri.IdnHost, uri.Port, null, proxyUri);
}
else
{
@@ -190,16 +195,16 @@ namespace System.Net.Http
else
{
// Tunnel SSL connection through proxy to the destination.
- return new HttpConnectionKey(HttpConnectionKind.SslProxyTunnel, uri.IdnHost, uri.Port, sslHostName, proxyUri);
+ return new HttpConnectionKey(HttpConnectionKind.SslProxyTunnel, isIPv6Address ? uri.Host : uri.IdnHost, uri.Port, sslHostName, proxyUri);
}
}
else if (sslHostName != null)
{
- return new HttpConnectionKey(HttpConnectionKind.Https, uri.IdnHost, uri.Port, sslHostName, null);
+ return new HttpConnectionKey(HttpConnectionKind.Https, isIPv6Address ? uri.Host : uri.IdnHost, uri.Port, sslHostName, null);
}
else
{
- return new HttpConnectionKey(HttpConnectionKind.Http, uri.IdnHost, uri.Port, null, null);
+ return new HttpConnectionKey(HttpConnectionKind.Http, isIPv6Address ? uri.Host : uri.IdnHost, uri.Port, null, null);
}
}
diff --git a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs
index e35a5843b7..945f5d3140 100644
--- a/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs
+++ b/src/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs
@@ -471,6 +471,67 @@ namespace System.Net.Http.Functional.Tests
}
}
+ [Theory]
+ [InlineData("[::1234]")]
+ [InlineData("[::1234]:8080")]
+ public async Task GetAsync_IPv6AddressInHostHeader_CorrectlyFormatted(string host)
+ {
+ string ipv6Address = "http://" + host;
+ bool connectionAccepted = false;
+
+ await LoopbackServer.CreateClientAndServerAsync(async proxyUri =>
+ {
+ using (HttpClientHandler handler = CreateHttpClientHandler())
+ using (var client = new HttpClient(handler))
+ {
+ handler.Proxy = new WebProxy(proxyUri);
+ try { await client.GetAsync(ipv6Address); } catch { }
+ }
+ }, server => server.AcceptConnectionAsync(async connection =>
+ {
+ connectionAccepted = true;
+ List<string> headers = await connection.ReadRequestHeaderAndSendResponseAsync();
+ Assert.Contains($"Host: {host}", headers);
+ }));
+
+ Assert.True(connectionAccepted);
+ }
+
+ public static IEnumerable<object[]> SecureAndNonSecure_IPBasedUri_MemberData() =>
+ from address in new[] { IPAddress.Loopback, IPAddress.IPv6Loopback }
+ from useSsl in new[] { true, false }
+ select new object[] { address, useSsl };
+
+ [Theory]
+ [MemberData(nameof(SecureAndNonSecure_IPBasedUri_MemberData))]
+ public async Task GetAsync_SecureAndNonSecureIPBasedUri_CorrectlyFormatted(IPAddress address, bool useSsl)
+ {
+ var options = new LoopbackServer.Options { Address = address, UseSsl= useSsl };
+ bool connectionAccepted = false;
+ string host = "";
+
+ await LoopbackServer.CreateClientAndServerAsync(async url =>
+ {
+ host = $"{url.Host}:{url.Port}";
+ using (HttpClientHandler handler = CreateHttpClientHandler())
+ using (var client = new HttpClient(handler))
+ {
+ if (useSsl)
+ {
+ handler.ServerCertificateCustomValidationCallback = TestHelper.AllowAllCertificates;
+ }
+ try { await client.GetAsync(url); } catch { }
+ }
+ }, server => server.AcceptConnectionAsync(async connection =>
+ {
+ connectionAccepted = true;
+ List<string> headers = await connection.ReadRequestHeaderAndSendResponseAsync();
+ Assert.Contains($"Host: {host}", headers);
+ }), options);
+
+ Assert.True(connectionAccepted);
+ }
+
[OuterLoop] // TODO: Issue #11345
[Theory, MemberData(nameof(CompressedServers))]
public async Task GetAsync_SetAutomaticDecompression_HeadersRemoved(Uri server)