@@ -91,7 +91,7 @@ public class AndroidClientHandler : HttpClientHandler
9191 bool decompress_here ;
9292
9393 URL java_url ;
94- URLConnection java_connection ;
94+ HttpURLConnection java_connection ;
9595
9696 /// <summary>
9797 /// <para>
@@ -189,33 +189,30 @@ protected void AssertSelf ()
189189 if ( ! request . RequestUri . IsAbsoluteUri )
190190 throw new ArgumentException ( "Must represent an absolute URI" , "request" ) ;
191191
192- /*using (*/ java_url = new URL ( request . RequestUri . ToString ( ) ) ; /*) {*/
193- /*using (*/ java_connection = java_url . OpenConnection ( ) ; /*) {*/
194- HttpURLConnection httpConnection = SetupRequestInternal ( request , java_connection ) ;
192+ java_url = new URL ( request . RequestUri . ToString ( ) ) ;
193+ java_connection = java_url . OpenConnection ( ) as HttpURLConnection ;
194+ HttpURLConnection httpConnection = await SetupRequestInternal ( request , java_connection ) . ConfigureAwait ( false ) ;
195195 return await ProcessRequest ( request , httpConnection , cancellationToken ) ;
196- /*}
197- }*/
198196 }
199197
200- async Task < HttpResponseMessage > ProcessRequest ( HttpRequestMessage request , HttpURLConnection httpConnection , CancellationToken cancellationToken )
198+ Task < HttpResponseMessage > ProcessRequest ( HttpRequestMessage request , HttpURLConnection httpConnection , CancellationToken cancellationToken )
201199 {
202200 cancellationToken . ThrowIfCancellationRequested ( ) ;
203201 httpConnection . InstanceFollowRedirects = AllowAutoRedirect ;
204202 RequestedAuthentication = null ;
205203 ProxyAuthenticationRequested = false ;
206204
207- return await Task < HttpResponseMessage > . Factory . StartNew ( ( ) => DoProcessRequest ( request , httpConnection , cancellationToken ) , cancellationToken ) . ConfigureAwait ( false ) ;
205+ return DoProcessRequest ( request , httpConnection , cancellationToken ) ;
208206 }
209207
210- HttpResponseMessage DoProcessRequest ( HttpRequestMessage request , HttpURLConnection httpConnection , CancellationToken cancellationToken )
208+ async Task < HttpResponseMessage > DoProcessRequest ( HttpRequestMessage request , HttpURLConnection httpConnection , CancellationToken cancellationToken )
211209 {
212210 if ( Logger . LogNet )
213211 Logger . Log ( LogLevel . Info , LOG_APP , $ "{ this } .DoProcessRequest ()") ;
214- httpConnection . RequestMethod = request . Method . ToString ( ) ;
215212 try {
216213 if ( Logger . LogNet )
217214 Logger . Log ( LogLevel . Info , LOG_APP , $ " connecting") ;
218- httpConnection . Connect ( ) ;
215+ await httpConnection . ConnectAsync ( ) . ConfigureAwait ( false ) ;
219216 if ( Logger . LogNet )
220217 Logger . Log ( LogLevel . Info , LOG_APP , $ " connected") ;
221218 } catch ( Java . Net . ConnectException ex ) {
@@ -372,9 +369,9 @@ void CopyHeaders (HttpURLConnection httpConnection, HttpResponseMessage response
372369 /// </summary>
373370 /// <param name="request">Request data</param>
374371 /// <param name="conn">Pre-configured connection instance</param>
375- protected virtual void SetupRequest ( HttpRequestMessage request , HttpURLConnection conn )
372+ protected virtual Task SetupRequest ( HttpRequestMessage request , HttpURLConnection conn )
376373 {
377- AssertSelf ( ) ;
374+ return Task . Factory . StartNew ( AssertSelf ) ;
378375 }
379376
380377 /// <summary>
@@ -433,20 +430,20 @@ void AppendEncoding (string encoding, ref List <string> list)
433430 list . Add ( encoding ) ;
434431 }
435432
436- HttpURLConnection SetupRequestInternal ( HttpRequestMessage request , URLConnection conn )
433+ async Task < HttpURLConnection > SetupRequestInternal ( HttpRequestMessage request , HttpURLConnection conn )
437434 {
438435 if ( conn == null )
439436 throw new ArgumentNullException ( nameof ( conn ) ) ;
440- var httpConnection = conn . JavaCast < HttpURLConnection > ( ) ;
437+ var httpConnection = conn ;
441438 if ( httpConnection == null )
442439 throw new InvalidOperationException ( $ "Unsupported URL scheme { conn . URL . Protocol } ") ;
443-
440+ httpConnection . RequestMethod = request . Method . ToString ( ) ;
444441 // SSL context must be set up as soon as possible, before adding any content or
445442 // headers. Otherwise Java won't use the socket factory
446- SetupSSL ( httpConnection as HttpsURLConnection ) ;
443+ await SetupSSL ( httpConnection as HttpsURLConnection ) ;
447444 if ( request . Content != null )
448- AddHeaders ( httpConnection , request . Content . Headers ) ;
449- AddHeaders ( httpConnection , request . Headers ) ;
445+ await AddHeaders ( httpConnection , request . Content . Headers ) ;
446+ await AddHeaders ( httpConnection , request . Headers ) ;
450447
451448 List < string > accept_encoding = null ;
452449
@@ -475,15 +472,16 @@ HttpURLConnection SetupRequestInternal (HttpRequestMessage request, URLConnectio
475472 httpConnection . SetRequestProperty ( "Cookie" , cookieHeaderValue ) ;
476473 }
477474
478- HandlePreAuthentication ( httpConnection ) ;
479- SetupRequest ( request , httpConnection ) ;
480- SetupRequestBody ( httpConnection , request ) ;
475+ await HandlePreAuthentication ( httpConnection ) ;
476+ await SetupRequest ( request , httpConnection ) ;
477+ await SetupRequestBody ( httpConnection , request ) ;
481478
482479 return httpConnection ;
483480 }
484481
485- void SetupSSL ( HttpsURLConnection httpsConnection )
482+ Task SetupSSL ( HttpsURLConnection httpsConnection )
486483 {
484+ return Task . Factory . StartNew ( ( ) => {
487485 if ( httpsConnection == null )
488486 return ;
489487
@@ -516,10 +514,12 @@ void SetupSSL (HttpsURLConnection httpsConnection)
516514 SSLContext context = SSLContext . GetInstance ( "TLS" ) ;
517515 context . Init ( kmf ? . GetKeyManagers ( ) , tmf . GetTrustManagers ( ) , null ) ;
518516 httpsConnection . SSLSocketFactory = context . SocketFactory ;
517+ } ) ;
519518 }
520519
521- void HandlePreAuthentication ( HttpURLConnection httpConnection )
520+ Task HandlePreAuthentication ( HttpURLConnection httpConnection )
522521 {
522+ return Task . Factory . StartNew ( ( ) => {
523523 AuthenticationData data = PreAuthenticationData ;
524524 if ( ! PreAuthenticate || data == null )
525525 return ;
@@ -548,37 +548,55 @@ void HandlePreAuthentication (HttpURLConnection httpConnection)
548548 if ( Logger . LogNet )
549549 Logger . Log ( LogLevel . Info , LOG_APP , $ "Authentication header '{ data . UseProxyAuthentication ? "Proxy-Authorization" : "Authorization" } ' will be set to '{ authorization . Message } '") ;
550550 httpConnection . SetRequestProperty ( data . UseProxyAuthentication ? "Proxy-Authorization" : "Authorization" , authorization . Message ) ;
551+ } ) ;
551552 }
552553
553- void AddHeaders ( HttpURLConnection conn , HttpHeaders headers )
554+ Task AddHeaders ( HttpURLConnection conn , HttpHeaders headers )
554555 {
556+ return Task . Factory . StartNew ( ( ) => {
555557 if ( headers == null )
556558 return ;
557559
558560 foreach ( KeyValuePair < string , IEnumerable < string > > header in headers ) {
559561 conn . SetRequestProperty ( header . Key , header . Value != null ? String . Join ( "," , header . Value ) : String . Empty ) ;
560562 }
563+ } ) ;
561564 }
562565
563- void SetupRequestBody ( HttpURLConnection conn , HttpRequestMessage request )
566+ async Task SetupRequestBody ( HttpURLConnection httpConnection , HttpRequestMessage request )
564567 {
565568 if ( request . Content == null ) {
569+ httpConnection . SetChunkedStreamingMode ( 0 ) ;
566570 // Pilfered from System.Net.Http.HttpClientHandler:SendAync
567571 if ( HttpMethod . Post . Equals ( request . Method ) || HttpMethod . Put . Equals ( request . Method ) || HttpMethod . Delete . Equals ( request . Method ) ) {
568572 // Explicitly set this to make sure we're sending a "Content-Length: 0" header.
569573 // This fixes the issue that's been reported on the forums:
570574 // http://forums.xamarin.com/discussion/17770/length-required-error-in-http-post-since-latest-release
571- conn . SetRequestProperty ( "Content-Length" , "0" ) ;
575+ httpConnection . SetRequestProperty ( "Content-Length" , "0" ) ;
572576 }
573577 return ;
574578 }
575579
576- conn . DoOutput = true ;
577- long ? contentLength = request . Content . Headers . ContentLength ;
578- if ( contentLength != null )
579- conn . SetFixedLengthStreamingMode ( ( int ) contentLength ) ;
580+ httpConnection . DoOutput = true ;
581+
582+ var bytes = await request . Content . ReadAsByteArrayAsync ( ) . ConfigureAwait ( false ) ;
583+
584+ int contentLength = bytes . Length ;
585+ httpConnection . SetRequestProperty ( "Content-Length" , contentLength . ToString ( ) ) ;
586+ httpConnection . SetFixedLengthStreamingMode ( contentLength ) ;
587+
588+ string contentType ;
589+ if ( request . Content . Headers . ContentType != null )
590+ contentType = String . Join ( " " , request . Content . Headers . GetValues ( "Content-Type" ) ) ;
580591 else
581- conn . SetChunkedStreamingMode ( 0 ) ;
592+ contentType = "text/plain" ;
593+ httpConnection . SetRequestProperty ( "Content-Type" , contentType ) ;
594+
595+ await Task . Factory . StartNew ( ( ) => {
596+ httpConnection . OutputStream . Write ( bytes , 0 , contentLength ) ;
597+ httpConnection . OutputStream . Flush ( ) ;
598+ httpConnection . OutputStream . Close ( ) ;
599+ } ) ;
582600 }
583601 }
584602}
0 commit comments