Skip to content

Commit 4146af1

Browse files
committed
add option to use native dotnet http handler for http(s)
1 parent 136a287 commit 4146af1

File tree

4 files changed

+48
-13
lines changed

4 files changed

+48
-13
lines changed

src/Docker.DotNet.X509/CertificateCredentials.cs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Security.Authentication;
4+
15
namespace Docker.DotNet.X509;
26

37
public class CertificateCredentials : Credentials
@@ -24,17 +28,37 @@ public override bool IsTlsCredentials()
2428

2529
public override HttpMessageHandler GetHandler(HttpMessageHandler handler)
2630
{
27-
if (handler is not ManagedHandler managedHandler)
31+
if (handler is ManagedHandler managedHandler)
2832
{
29-
return handler;
33+
if (!managedHandler.ClientCertificates.Contains(_certificate))
34+
{
35+
managedHandler.ClientCertificates.Add(_certificate);
36+
}
37+
38+
managedHandler.ServerCertificateValidationCallback = ServerCertificateValidationCallback;
39+
40+
return managedHandler;
3041
}
3142

32-
if (!managedHandler.ClientCertificates.Contains(_certificate))
43+
if (handler is HttpClientHandler nativeHandler)
3344
{
34-
managedHandler.ClientCertificates.Add(_certificate);
35-
}
45+
if (!nativeHandler.ClientCertificates.Contains(_certificate))
46+
{
47+
nativeHandler.ClientCertificates.Add(_certificate);
48+
}
49+
50+
nativeHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
51+
nativeHandler.CheckCertificateRevocationList = false;
52+
nativeHandler.AllowAutoRedirect = false;
53+
nativeHandler.UseProxy = false;
54+
nativeHandler.AllowAutoRedirect = true;
55+
nativeHandler.MaxAutomaticRedirections = 20;
56+
nativeHandler.Proxy = null;
57+
nativeHandler.SslProtocols = SslProtocols.Tls12;
58+
nativeHandler.ServerCertificateCustomValidationCallback += (message, certificate, chain, errors) => ServerCertificateValidationCallback?.Invoke(message, certificate, chain, errors) ?? false;
3659

37-
managedHandler.ServerCertificateValidationCallback = ServerCertificateValidationCallback;
60+
return nativeHandler;
61+
}
3862

3963
return handler;
4064
}

src/Docker.DotNet/DockerClient.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ internal DockerClient(DockerClientConfiguration configuration, Version requested
3434
Plugin = new PluginOperations(this);
3535
Exec = new ExecOperations(this);
3636

37-
ManagedHandler handler;
37+
HttpMessageHandler handler;
3838
var uri = Configuration.EndpointBaseUri;
3939
switch (uri.Scheme.ToLowerInvariant())
4040
{
@@ -80,11 +80,17 @@ await stream.ConnectAsync(timeout, cancellationToken)
8080
Scheme = configuration.Credentials.IsTlsCredentials() ? "https" : "http"
8181
};
8282
uri = builder.Uri;
83-
handler = new ManagedHandler(logger);
83+
if (configuration.NativeHttpHandler)
84+
handler = new HttpClientHandler();
85+
else
86+
handler = new ManagedHandler(logger);
8487
break;
8588

8689
case "https":
87-
handler = new ManagedHandler(logger);
90+
if (configuration.NativeHttpHandler)
91+
handler = new HttpClientHandler();
92+
else
93+
handler = new ManagedHandler(logger);
8894
break;
8995

9096
case "unix":

src/Docker.DotNet/DockerClientConfiguration.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ public DockerClientConfiguration(
88
Credentials credentials = null,
99
TimeSpan defaultTimeout = default,
1010
TimeSpan namedPipeConnectTimeout = default,
11-
IReadOnlyDictionary<string, string> defaultHttpRequestHeaders = null)
12-
: this(GetLocalDockerEndpoint(), credentials, defaultTimeout, namedPipeConnectTimeout, defaultHttpRequestHeaders)
11+
IReadOnlyDictionary<string, string> defaultHttpRequestHeaders = null,
12+
bool nativeHttpHandler = false)
13+
: this(GetLocalDockerEndpoint(), credentials, defaultTimeout, namedPipeConnectTimeout, defaultHttpRequestHeaders, nativeHttpHandler)
1314
{
1415
}
1516

@@ -18,7 +19,8 @@ public DockerClientConfiguration(
1819
Credentials credentials = null,
1920
TimeSpan defaultTimeout = default,
2021
TimeSpan namedPipeConnectTimeout = default,
21-
IReadOnlyDictionary<string, string> defaultHttpRequestHeaders = null)
22+
IReadOnlyDictionary<string, string> defaultHttpRequestHeaders = null,
23+
bool nativeHttpHandler = false)
2224
{
2325
if (endpoint == null)
2426
{
@@ -35,6 +37,7 @@ public DockerClientConfiguration(
3537
DefaultTimeout = TimeSpan.Equals(TimeSpan.Zero, defaultTimeout) ? TimeSpan.FromSeconds(100) : defaultTimeout;
3638
NamedPipeConnectTimeout = TimeSpan.Equals(TimeSpan.Zero, namedPipeConnectTimeout) ? TimeSpan.FromMilliseconds(100) : namedPipeConnectTimeout;
3739
DefaultHttpRequestHeaders = defaultHttpRequestHeaders ?? new Dictionary<string, string>();
40+
NativeHttpHandler = nativeHttpHandler;
3841
}
3942

4043
/// <summary>
@@ -50,6 +53,8 @@ public DockerClientConfiguration(
5053

5154
public TimeSpan NamedPipeConnectTimeout { get; }
5255

56+
public bool NativeHttpHandler { get; }
57+
5358
public DockerClient CreateClient(Version requestedApiVersion = null, ILogger logger = null)
5459
{
5560
return new DockerClient(this, requestedApiVersion, logger);

test/Docker.DotNet.Tests/TestFixture.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public sealed class TestFixture : Progress<JSONMessage>, IAsyncLifetime, IDispos
2121
public TestFixture(IMessageSink messageSink)
2222
{
2323
_messageSink = messageSink;
24-
DockerClientConfiguration = new DockerClientConfiguration();
24+
DockerClientConfiguration = new DockerClientConfiguration(nativeHttpHandler: true);
2525
DockerClient = DockerClientConfiguration.CreateClient(logger: this);
2626
Cts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
2727
Cts.Token.Register(() => throw new TimeoutException("Docker.DotNet tests timed out."));

0 commit comments

Comments
 (0)