1
1
using System ;
2
2
using System . IO ;
3
+ using System . Linq ;
3
4
using System . Net ;
5
+ using System . Net . Http ;
4
6
using System . Net . Security ;
7
+ using System . Security . Authentication ;
5
8
using System . Security . Cryptography . X509Certificates ;
6
9
7
10
namespace LibGit2Sharp . Core
@@ -49,12 +52,34 @@ private class ManagedHttpSmartSubtransportStream : SmartSubtransportStream
49
52
private MemoryStream postBuffer = new MemoryStream ( ) ;
50
53
private Stream responseStream ;
51
54
55
+ private HttpClientHandler httpClientHandler ;
56
+ private HttpClient httpClient ;
57
+
52
58
public ManagedHttpSmartSubtransportStream ( ManagedHttpSmartSubtransport parent , string endpointUrl , bool isPost , string contentType )
53
59
: base ( parent )
54
60
{
55
61
EndpointUrl = new Uri ( endpointUrl ) ;
56
62
IsPost = isPost ;
57
63
ContentType = contentType ;
64
+
65
+ httpClientHandler = CreateClientHandler ( ) ;
66
+ httpClient = new HttpClient ( httpClientHandler ) ;
67
+ }
68
+
69
+ private HttpClientHandler CreateClientHandler ( )
70
+ {
71
+ var httpClientHandler = new HttpClientHandler ( ) ;
72
+
73
+ httpClientHandler . AllowAutoRedirect = false ;
74
+ httpClientHandler . ServerCertificateCustomValidationCallback = CertificateValidationProxy ;
75
+
76
+ #if ! NETFRAMEWORK
77
+ httpClientHandler . SslProtocols = SslProtocols . Tls12 ;
78
+ #else
79
+ ServicePointManager . SecurityProtocol = SecurityProtocolType . Tls12 ;
80
+ #endif
81
+
82
+ return httpClientHandler ;
58
83
}
59
84
60
85
private Uri EndpointUrl
@@ -104,13 +129,21 @@ public override int Write(Stream dataStream, long length)
104
129
105
130
private bool CertificateValidationProxy ( object sender , X509Certificate cert , X509Chain chain , SslPolicyErrors errors )
106
131
{
107
- int ret = SmartTransport . CertificateCheck ( new CertificateX509 ( cert ) , ( errors == SslPolicyErrors . None ) , EndpointUrl . Host ) ;
108
- Ensure . ZeroResult ( ret ) ;
132
+ try
133
+ {
134
+ int ret = SmartTransport . CertificateCheck ( new CertificateX509 ( cert ) , ( errors == SslPolicyErrors . None ) , EndpointUrl . Host ) ;
135
+ Ensure . ZeroResult ( ret ) ;
109
136
110
- return true ;
137
+ return true ;
138
+ }
139
+ catch ( Exception e )
140
+ {
141
+ SetError ( e ) ;
142
+ return false ;
143
+ }
111
144
}
112
145
113
- private string getUserAgent ( )
146
+ private string GetUserAgent ( )
114
147
{
115
148
string userAgent = GlobalSettings . GetUserAgent ( ) ;
116
149
@@ -122,97 +155,76 @@ private string getUserAgent()
122
155
return userAgent ;
123
156
}
124
157
125
- private HttpWebRequest CreateWebRequest ( Uri endpointUrl , bool isPost , string contentType )
158
+ private HttpRequestMessage CreateRequest ( Uri endpointUrl , bool isPost , string contentType )
126
159
{
127
- ServicePointManager . SecurityProtocol = SecurityProtocolType . Tls12 ;
128
-
129
- HttpWebRequest webRequest = ( HttpWebRequest ) HttpWebRequest . Create ( endpointUrl ) ;
130
- webRequest . UserAgent = String . Format ( "git/2.0 ({0})" , getUserAgent ( ) ) ;
131
- webRequest . ServicePoint . Expect100Continue = false ;
132
- webRequest . AllowAutoRedirect = false ;
133
- webRequest . ServerCertificateValidationCallback += CertificateValidationProxy ;
160
+ var verb = isPost ? new HttpMethod ( "POST" ) : new HttpMethod ( "GET" ) ;
161
+ var request = new HttpRequestMessage ( verb , endpointUrl ) ;
162
+ request . Headers . Add ( "User-Agent" , String . Format ( "git/2.0 ({0})" , GetUserAgent ( ) ) ) ;
163
+ request . Headers . Remove ( "Expect" ) ;
134
164
135
- if ( isPost )
136
- {
137
- webRequest . Method = "POST" ;
138
- webRequest . ContentType = contentType ;
139
- }
140
-
141
- return webRequest ;
165
+ return request ;
142
166
}
143
167
144
- private HttpWebResponse GetResponseWithRedirects ( )
168
+ private HttpResponseMessage GetResponseWithRedirects ( )
145
169
{
146
- HttpWebRequest request = CreateWebRequest ( EndpointUrl , IsPost , ContentType ) ;
147
- HttpWebResponse response = null ;
170
+ ICredentials credentials = null ;
171
+ var url = EndpointUrl ;
148
172
int retries ;
149
173
150
174
for ( retries = 0 ; ; retries ++ )
151
175
{
152
- if ( retries > MAX_REDIRECTS )
153
- {
154
- throw new Exception ( "too many redirects or authentication replays" ) ;
155
- }
176
+ var httpClientHandler = CreateClientHandler ( ) ;
177
+ httpClientHandler . Credentials = credentials ;
156
178
157
- if ( IsPost && postBuffer . Length > 0 )
179
+ using ( var httpClient = new HttpClient ( httpClientHandler ) )
158
180
{
159
- postBuffer . Seek ( 0 , SeekOrigin . Begin ) ;
181
+ var request = CreateRequest ( url , IsPost , ContentType ) ;
160
182
161
- using ( Stream requestStream = request . GetRequestStream ( ) )
183
+ if ( retries > MAX_REDIRECTS )
162
184
{
163
- postBuffer . WriteTo ( requestStream ) ;
185
+ throw new Exception ( "too many redirects or authentication replays" ) ;
164
186
}
165
- }
166
187
167
- try
168
- {
169
- response = ( HttpWebResponse ) request . GetResponse ( ) ;
170
- }
171
- catch ( WebException ex )
172
- {
173
- if ( ex . Response != null )
188
+ if ( IsPost && postBuffer . Length > 0 )
174
189
{
175
- response = ( HttpWebResponse ) ex . Response ;
190
+ var bufferDup = new MemoryStream ( postBuffer . GetBuffer ( ) ) ;
191
+ bufferDup . Seek ( 0 , SeekOrigin . Begin ) ;
192
+
193
+ request . Content = new StreamContent ( bufferDup ) ;
194
+ request . Content . Headers . Add ( "Content-Type" , ContentType ) ;
176
195
}
177
- else if ( ex . InnerException != null )
196
+
197
+ var response = httpClient . SendAsync ( request ) . Result ;
198
+
199
+ if ( response . StatusCode == HttpStatusCode . OK )
178
200
{
179
- throw ex . InnerException ;
201
+ return response ;
180
202
}
181
- else
203
+ else if ( response . StatusCode == HttpStatusCode . Unauthorized )
182
204
{
183
- throw new Exception ( "unknown network failure" ) ;
184
- }
185
- }
205
+ Credentials cred ;
206
+ int ret = SmartTransport . AcquireCredentials ( out cred , null , typeof ( UsernamePasswordCredentials ) ) ;
186
207
187
- if ( response . StatusCode == HttpStatusCode . OK )
188
- {
189
- break ;
190
- }
191
- else if ( response . StatusCode == HttpStatusCode . Unauthorized )
192
- {
193
- Credentials cred ;
194
- int ret = SmartTransport . AcquireCredentials ( out cred , null , typeof ( UsernamePasswordCredentials ) ) ;
208
+ if ( ret != 0 )
209
+ {
210
+ throw new InvalidOperationException ( "authentication cancelled" ) ;
211
+ }
195
212
196
- if ( ret != 0 )
213
+ UsernamePasswordCredentials userpass = ( UsernamePasswordCredentials ) cred ;
214
+ credentials = new NetworkCredential ( userpass . Username , userpass . Password ) ;
215
+ continue ;
216
+ }
217
+ else if ( response . StatusCode == HttpStatusCode . Moved || response . StatusCode == HttpStatusCode . Redirect )
197
218
{
198
- throw new InvalidOperationException ( "authentication cancelled" ) ;
219
+ url = new Uri ( response . Headers . GetValues ( "Location" ) . First ( ) ) ;
220
+ continue ;
199
221
}
200
222
201
- request = CreateWebRequest ( EndpointUrl , IsPost , ContentType ) ;
202
- UsernamePasswordCredentials userpass = ( UsernamePasswordCredentials ) cred ;
203
- request . Credentials = new NetworkCredential ( userpass . Username , userpass . Password ) ;
204
- continue ;
205
- }
206
- else if ( response . StatusCode == HttpStatusCode . Moved || response . StatusCode == HttpStatusCode . Redirect )
207
- {
208
- request = CreateWebRequest ( new Uri ( response . Headers [ "Location" ] ) , IsPost , ContentType ) ;
209
- continue ;
223
+ throw new Exception ( string . Format ( "unexpected HTTP response: {0}" , response . StatusCode ) ) ;
210
224
}
211
-
212
- throw new Exception ( string . Format ( "unexpected HTTP response: {0}" , response . StatusCode ) ) ;
213
225
}
214
226
215
- return response ;
227
+ throw new Exception ( "too many redirects or authentication replays" ) ;
216
228
}
217
229
218
230
public override int Read ( Stream dataStream , long length , out long readTotal )
@@ -222,8 +234,8 @@ public override int Read(Stream dataStream, long length, out long readTotal)
222
234
223
235
if ( responseStream == null )
224
236
{
225
- HttpWebResponse response = GetResponseWithRedirects ( ) ;
226
- responseStream = response . GetResponseStream ( ) ;
237
+ HttpResponseMessage response = GetResponseWithRedirects ( ) ;
238
+ responseStream = ( response . Content as StreamContent ) . ReadAsStreamAsync ( ) . Result ;
227
239
}
228
240
229
241
while ( length > 0 )
@@ -249,6 +261,12 @@ protected override void Free()
249
261
responseStream = null ;
250
262
}
251
263
264
+ if ( httpClient != null )
265
+ {
266
+ httpClient . Dispose ( ) ;
267
+ httpClient = null ;
268
+ }
269
+
252
270
base . Free ( ) ;
253
271
}
254
272
}
0 commit comments