diff --git a/src/Mono.Android/Xamarin.Android.Net/AndroidClientHandler.cs b/src/Mono.Android/Xamarin.Android.Net/AndroidClientHandler.cs
index e1d6a138b10..6d8dfcdb551 100644
--- a/src/Mono.Android/Xamarin.Android.Net/AndroidClientHandler.cs
+++ b/src/Mono.Android/Xamarin.Android.Net/AndroidClientHandler.cs
@@ -91,7 +91,7 @@ public class AndroidClientHandler : HttpClientHandler
bool decompress_here;
URL java_url;
- URLConnection java_connection;
+ HttpURLConnection java_connection;
///
///
@@ -189,33 +189,30 @@ protected void AssertSelf ()
if (!request.RequestUri.IsAbsoluteUri)
throw new ArgumentException ("Must represent an absolute URI", "request");
- /*using (*/java_url = new URL (request.RequestUri.ToString ());/*) {*/
- /*using (*/java_connection = java_url.OpenConnection ();/*) {*/
- HttpURLConnection httpConnection = SetupRequestInternal (request, java_connection);
+ java_url = new URL (request.RequestUri.ToString ());
+ java_connection = java_url.OpenConnection () as HttpURLConnection;
+ HttpURLConnection httpConnection = await SetupRequestInternal (request, java_connection).ConfigureAwait (false);
return await ProcessRequest (request, httpConnection, cancellationToken);
- /*}
- }*/
}
- async Task ProcessRequest (HttpRequestMessage request, HttpURLConnection httpConnection, CancellationToken cancellationToken)
+ Task ProcessRequest (HttpRequestMessage request, HttpURLConnection httpConnection, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested ();
httpConnection.InstanceFollowRedirects = AllowAutoRedirect;
RequestedAuthentication = null;
ProxyAuthenticationRequested = false;
- return await Task.Factory.StartNew (() => DoProcessRequest (request, httpConnection, cancellationToken), cancellationToken).ConfigureAwait (false);
+ return DoProcessRequest (request, httpConnection, cancellationToken);
}
- HttpResponseMessage DoProcessRequest (HttpRequestMessage request, HttpURLConnection httpConnection, CancellationToken cancellationToken)
+ async Task DoProcessRequest (HttpRequestMessage request, HttpURLConnection httpConnection, CancellationToken cancellationToken)
{
if (Logger.LogNet)
Logger.Log (LogLevel.Info, LOG_APP, $"{this}.DoProcessRequest ()");
- httpConnection.RequestMethod = request.Method.ToString ();
try {
if (Logger.LogNet)
Logger.Log (LogLevel.Info, LOG_APP, $" connecting");
- httpConnection.Connect ();
+ await httpConnection.ConnectAsync ().ConfigureAwait (false);
if (Logger.LogNet)
Logger.Log (LogLevel.Info, LOG_APP, $" connected");
} catch (Java.Net.ConnectException ex) {
@@ -372,9 +369,9 @@ void CopyHeaders (HttpURLConnection httpConnection, HttpResponseMessage response
///
/// Request data
/// Pre-configured connection instance
- protected virtual void SetupRequest (HttpRequestMessage request, HttpURLConnection conn)
+ protected virtual Task SetupRequest (HttpRequestMessage request, HttpURLConnection conn)
{
- AssertSelf ();
+ return Task.Factory.StartNew (AssertSelf);
}
///
@@ -433,20 +430,20 @@ void AppendEncoding (string encoding, ref List list)
list.Add (encoding);
}
- HttpURLConnection SetupRequestInternal (HttpRequestMessage request, URLConnection conn)
+ async Task SetupRequestInternal (HttpRequestMessage request, HttpURLConnection conn)
{
if (conn == null)
throw new ArgumentNullException (nameof (conn));
- var httpConnection = conn.JavaCast ();
+ var httpConnection = conn;
if (httpConnection == null)
throw new InvalidOperationException ($"Unsupported URL scheme {conn.URL.Protocol}");
-
+ httpConnection.RequestMethod = request.Method.ToString ();
// SSL context must be set up as soon as possible, before adding any content or
// headers. Otherwise Java won't use the socket factory
- SetupSSL (httpConnection as HttpsURLConnection);
+ await SetupSSL (httpConnection as HttpsURLConnection);
if (request.Content != null)
- AddHeaders (httpConnection, request.Content.Headers);
- AddHeaders (httpConnection, request.Headers);
+ await AddHeaders (httpConnection, request.Content.Headers);
+ await AddHeaders (httpConnection, request.Headers);
List accept_encoding = null;
@@ -475,15 +472,16 @@ HttpURLConnection SetupRequestInternal (HttpRequestMessage request, URLConnectio
httpConnection.SetRequestProperty ("Cookie", cookieHeaderValue);
}
- HandlePreAuthentication (httpConnection);
- SetupRequest (request, httpConnection);
- SetupRequestBody (httpConnection, request);
+ await HandlePreAuthentication (httpConnection);
+ await SetupRequest (request, httpConnection);
+ await SetupRequestBody (httpConnection, request);
return httpConnection;
}
- void SetupSSL (HttpsURLConnection httpsConnection)
+ Task SetupSSL (HttpsURLConnection httpsConnection)
{
+ return Task.Factory.StartNew (() => {
if (httpsConnection == null)
return;
@@ -516,10 +514,12 @@ void SetupSSL (HttpsURLConnection httpsConnection)
SSLContext context = SSLContext.GetInstance ("TLS");
context.Init (kmf?.GetKeyManagers (), tmf.GetTrustManagers (), null);
httpsConnection.SSLSocketFactory = context.SocketFactory;
+ });
}
- void HandlePreAuthentication (HttpURLConnection httpConnection)
+ Task HandlePreAuthentication (HttpURLConnection httpConnection)
{
+ return Task.Factory.StartNew (() => {
AuthenticationData data = PreAuthenticationData;
if (!PreAuthenticate || data == null)
return;
@@ -548,37 +548,55 @@ void HandlePreAuthentication (HttpURLConnection httpConnection)
if (Logger.LogNet)
Logger.Log (LogLevel.Info, LOG_APP, $"Authentication header '{data.UseProxyAuthentication ? "Proxy-Authorization" : "Authorization"}' will be set to '{authorization.Message}'");
httpConnection.SetRequestProperty (data.UseProxyAuthentication ? "Proxy-Authorization" : "Authorization", authorization.Message);
+ });
}
- void AddHeaders (HttpURLConnection conn, HttpHeaders headers)
+ Task AddHeaders (HttpURLConnection conn, HttpHeaders headers)
{
+ return Task.Factory.StartNew (() => {
if (headers == null)
return;
foreach (KeyValuePair> header in headers) {
conn.SetRequestProperty (header.Key, header.Value != null ? String.Join (",", header.Value) : String.Empty);
}
+ });
}
- void SetupRequestBody (HttpURLConnection conn, HttpRequestMessage request)
+ async Task SetupRequestBody (HttpURLConnection httpConnection, HttpRequestMessage request)
{
if (request.Content == null) {
+ httpConnection.SetChunkedStreamingMode (0);
// Pilfered from System.Net.Http.HttpClientHandler:SendAync
if (HttpMethod.Post.Equals (request.Method) || HttpMethod.Put.Equals (request.Method) || HttpMethod.Delete.Equals (request.Method)) {
// Explicitly set this to make sure we're sending a "Content-Length: 0" header.
// This fixes the issue that's been reported on the forums:
// http://forums.xamarin.com/discussion/17770/length-required-error-in-http-post-since-latest-release
- conn.SetRequestProperty ("Content-Length", "0");
+ httpConnection.SetRequestProperty ("Content-Length", "0");
}
return;
}
- conn.DoOutput = true;
- long? contentLength = request.Content.Headers.ContentLength;
- if (contentLength != null)
- conn.SetFixedLengthStreamingMode ((int)contentLength);
+ httpConnection.DoOutput = true;
+
+ var bytes = await request.Content.ReadAsByteArrayAsync ().ConfigureAwait (false);
+
+ int contentLength = bytes.Length;
+ httpConnection.SetRequestProperty ("Content-Length", contentLength.ToString());
+ httpConnection.SetFixedLengthStreamingMode (contentLength);
+
+ string contentType;
+ if (request.Content.Headers.ContentType != null)
+ contentType = String.Join (" ", request.Content.Headers.GetValues ("Content-Type"));
else
- conn.SetChunkedStreamingMode (0);
+ contentType = "text/plain";
+ httpConnection.SetRequestProperty ("Content-Type", contentType);
+
+ await Task.Factory.StartNew (() => {
+ httpConnection.OutputStream.Write (bytes, 0, contentLength);
+ httpConnection.OutputStream.Flush ();
+ httpConnection.OutputStream.Close ();
+ });
}
}
}