3
3
using System ;
4
4
using System . Collections . Generic ;
5
5
using System . Linq ;
6
+ using System . Net . Http ;
6
7
using System . Threading . Tasks ;
7
8
8
9
namespace Microsoft . Git . CredentialManager
@@ -45,7 +46,7 @@ public interface IHostProviderRegistry : IDisposable
45
46
46
47
/// <summary>
47
48
/// Host provider registry where each provider is queried by priority order until the first
48
- /// provider that supports the credential query is found.
49
+ /// provider that supports the credential query or matches the endpoint query is found.
49
50
/// </summary>
50
51
public class HostProviderRegistry : IHostProviderRegistry
51
52
{
@@ -87,7 +88,7 @@ public void Register(IHostProvider hostProvider, HostProviderPriority priority)
87
88
providers . Add ( hostProvider ) ;
88
89
}
89
90
90
- public Task < IHostProvider > GetProviderAsync ( InputArguments input )
91
+ public async Task < IHostProvider > GetProviderAsync ( InputArguments input )
91
92
{
92
93
IHostProvider provider ;
93
94
@@ -111,7 +112,7 @@ public Task<IHostProvider> GetProviderAsync(InputArguments input)
111
112
}
112
113
else
113
114
{
114
- return Task . FromResult ( provider ) ;
115
+ return provider ;
115
116
}
116
117
}
117
118
}
@@ -137,7 +138,7 @@ public Task<IHostProvider> GetProviderAsync(InputArguments input)
137
138
}
138
139
else
139
140
{
140
- return Task . FromResult ( provider ) ;
141
+ return provider ;
141
142
}
142
143
}
143
144
}
@@ -147,35 +148,51 @@ public Task<IHostProvider> GetProviderAsync(InputArguments input)
147
148
//
148
149
_context . Trace . WriteLine ( "Performing auto-detection of host provider." ) ;
149
150
150
- IHostProvider MatchProvider ( HostProviderPriority priority )
151
+ var uri = input . GetRemoteUri ( ) ;
152
+ var queryResponse = new Lazy < Task < HttpResponseMessage > > ( ( ) =>
153
+ {
154
+ _context . Trace . WriteLine ( "Querying remote URL for host provider auto-detection." ) ;
155
+ return HttpClient . HeadAsync ( uri ) ;
156
+ } ) ;
157
+
158
+ async Task < IHostProvider > MatchProviderAsync ( HostProviderPriority priority )
151
159
{
152
160
if ( _hostProviders . TryGetValue ( priority , out ICollection < IHostProvider > providers ) )
153
161
{
154
162
_context . Trace . WriteLine ( $ "Checking against { providers . Count } host providers registered with priority '{ priority } '.") ;
155
163
164
+ // Try matching using the static Git input arguments first (cheap)
156
165
if ( providers . TryGetFirst ( x => x . IsSupported ( input ) , out IHostProvider match ) )
157
166
{
158
167
return match ;
159
168
}
160
- }
161
169
162
- return null ;
163
- }
170
+ HttpResponseMessage response = await queryResponse . Value ;
164
171
165
- provider = MatchProvider ( HostProviderPriority . High ) ??
166
- MatchProvider ( HostProviderPriority . Normal ) ??
167
- MatchProvider ( HostProviderPriority . Low ) ;
172
+ // Try matching using the HTTP response from a query to the remote URL (expensive)
173
+ if ( providers . TryGetFirst ( x => x . IsSupported ( response ) , out match ) )
174
+ {
175
+ return match ;
176
+ }
177
+ }
168
178
169
- if ( provider is null )
170
- {
171
- throw new Exception ( "No host provider available to service this request." ) ;
179
+ return null ;
172
180
}
173
181
174
- return Task . FromResult ( provider ) ;
182
+ // Match providers starting with the highest priority
183
+ return await MatchProviderAsync ( HostProviderPriority . High ) ??
184
+ await MatchProviderAsync ( HostProviderPriority . Normal ) ??
185
+ await MatchProviderAsync ( HostProviderPriority . Low ) ??
186
+ throw new Exception ( "No host provider available to service this request." ) ;
175
187
}
176
188
189
+ private HttpClient _httpClient ;
190
+ private HttpClient HttpClient => _httpClient ??= _context . HttpClientFactory . CreateClient ( ) ;
191
+
177
192
public void Dispose ( )
178
193
{
194
+ _httpClient ? . Dispose ( ) ;
195
+
179
196
// Dispose of all registered providers to give them a chance to clean up and release any resources
180
197
foreach ( IHostProvider provider in _hostProviders . Values )
181
198
{
0 commit comments