-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Copy pathDefaultRegistryAPI.cs
99 lines (79 loc) · 3.54 KB
/
DefaultRegistryAPI.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Extensions.Logging;
namespace Microsoft.NET.Build.Containers;
internal class DefaultRegistryAPI : IRegistryAPI
{
private readonly Uri _baseUri;
private readonly HttpClient _client;
private readonly ILogger _logger;
// Empirical value - Unoptimized .NET application layers can be ~200MB
// * .NET Runtime (~80MB)
// * ASP.NET Runtime (~25MB)
// * application and dependencies - variable, but _probably_ not more than the BCL?
// Given a 200MB target and a 1Mb/s upload speed, we'd expect an upload speed of 27m:57s.
// Making this a round 30 for convenience.
private static TimeSpan LongRequestTimeout = TimeSpan.FromMinutes(30);
internal DefaultRegistryAPI(string registryName, Uri baseUri, bool isInsecureRegistry, ILogger logger)
{
_baseUri = baseUri;
_logger = logger;
_client = CreateClient(registryName, baseUri, isInsecureRegistry, logger);
Manifest = new DefaultManifestOperations(_baseUri, registryName, _client, _logger);
Blob = new DefaultBlobOperations(_baseUri, registryName, _client, _logger);
}
public IBlobOperations Blob { get; }
public IManifestOperations Manifest { get; }
private static HttpClient CreateClient(string registryName, Uri baseUri, bool isInsecureRegistry, ILogger logger)
{
HttpMessageHandler innerHandler = CreateHttpHandler(baseUri, isInsecureRegistry, logger);
HttpMessageHandler clientHandler = new AuthHandshakeMessageHandler(registryName, innerHandler, logger);
if (baseUri.IsAmazonECRRegistry())
{
clientHandler = new AmazonECRMessageHandler(clientHandler);
}
HttpClient client = new(clientHandler)
{
Timeout = LongRequestTimeout
};
client.DefaultRequestHeaders.Add("User-Agent", $".NET Container Library v{Constants.Version}");
return client;
}
private static HttpMessageHandler CreateHttpHandler(Uri baseUri, bool allowInsecure, ILogger logger)
{
var socketsHttpHandler = new SocketsHttpHandler()
{
UseCookies = false,
// the rest of the HTTP stack has an very long timeout (see below) but we should still have a reasonable timeout for the initial connection
ConnectTimeout = TimeSpan.FromSeconds(30)
};
if (!allowInsecure)
{
return socketsHttpHandler;
}
socketsHttpHandler.SslOptions = new System.Net.Security.SslClientAuthenticationOptions()
{
RemoteCertificateValidationCallback = IgnoreCertificateErrorsForSpecificHost(baseUri.Host)
};
return new FallbackToHttpMessageHandler(baseUri.Host, baseUri.Port, socketsHttpHandler, logger);
}
private static RemoteCertificateValidationCallback IgnoreCertificateErrorsForSpecificHost(string host)
{
return (object sender, X509Certificate? certificate, X509Chain? chain, SslPolicyErrors sslPolicyErrors) =>
{
if (sslPolicyErrors == SslPolicyErrors.None)
{
return true;
}
// Ignore certificate errors for the hostname.
if ((sender as SslStream)?.TargetHostName == host)
{
return true;
}
return false;
};
}
}