diff --git a/src/libraries/System.Net.Http/src/Resources/Strings.resx b/src/libraries/System.Net.Http/src/Resources/Strings.resx
index 1da773e718e25c..1b0be33fd7cb95 100644
--- a/src/libraries/System.Net.Http/src/Resources/Strings.resx
+++ b/src/libraries/System.Net.Http/src/Resources/Strings.resx
@@ -367,7 +367,7 @@
Cannot access a closed stream.
- Only the 'http', 'https', 'socks4', 'socks4a' and 'socks5' schemes are allowed for proxies.
+ Only the 'http', 'https', 'socks4', 'socks4a', 'socks5', and 'socks5h' schemes are allowed for proxies.
Request headers must contain only ASCII characters.
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpEnvironmentProxy.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpEnvironmentProxy.cs
index dab4ad49f7b0dd..09b9f7698f627b 100644
--- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpEnvironmentProxy.cs
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpEnvironmentProxy.cs
@@ -146,6 +146,11 @@ private HttpEnvironmentProxy(Uri? httpProxy, Uri? httpsProxy, string? bypassList
hostIndex = 9;
protocol = "socks5";
}
+ else if (value.StartsWith("socks5h://", StringComparison.OrdinalIgnoreCase))
+ {
+ hostIndex = 10;
+ protocol = "socks5h";
+ }
else if (value.StartsWith("socks4a://", StringComparison.OrdinalIgnoreCase))
{
hostIndex = 10;
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpUtilities.SocketsHttpHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpUtilities.SocketsHttpHandler.cs
index ed5f1c14459716..9fa5682c080bd5 100644
--- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpUtilities.SocketsHttpHandler.cs
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpUtilities.SocketsHttpHandler.cs
@@ -26,6 +26,7 @@ internal static bool IsSupportedProxyScheme(string scheme) =>
internal static bool IsSocksScheme(string scheme) =>
string.Equals(scheme, "socks5", StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(scheme, "socks5h", StringComparison.OrdinalIgnoreCase) ||
string.Equals(scheme, "socks4a", StringComparison.OrdinalIgnoreCase) ||
string.Equals(scheme, "socks4", StringComparison.OrdinalIgnoreCase);
}
diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocksHelper.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocksHelper.cs
index e34382b49f8ce3..f864c504359a15 100644
--- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocksHelper.cs
+++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocksHelper.cs
@@ -37,7 +37,8 @@ public static async ValueTask EstablishSocksTunnelAsync(Stream stream, string ho
{
NetworkCredential? credentials = proxyCredentials?.GetCredential(proxyUri, proxyUri.Scheme);
- if (string.Equals(proxyUri.Scheme, "socks5", StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(proxyUri.Scheme, "socks5", StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(proxyUri.Scheme, "socks5h", StringComparison.OrdinalIgnoreCase))
{
await EstablishSocks5TunnelAsync(stream, host, port, credentials, async).ConfigureAwait(false);
}
diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/SocksProxyTest.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/SocksProxyTest.cs
index 300ed02aff41ce..3705d67b32a4d1 100644
--- a/src/libraries/System.Net.Http/tests/FunctionalTests/SocksProxyTest.cs
+++ b/src/libraries/System.Net.Http/tests/FunctionalTests/SocksProxyTest.cs
@@ -15,12 +15,12 @@ public abstract class SocksProxyTest : HttpClientHandlerTestBase
{
public SocksProxyTest(ITestOutputHelper helper) : base(helper) { }
- private static string[] Hosts(string socksScheme) => socksScheme == "socks5"
+ private static string[] Hosts(string socksScheme) => socksScheme == "socks5" || socksScheme == "socks5h"
? new[] { "localhost", "127.0.0.1", "::1" }
: new[] { "localhost", "127.0.0.1" };
public static IEnumerable