[System]: WebClient.OpenWrite() must get the response on close; fixes #10163.
authorMartin Baulig <martin.baulig@xamarin.com>
Tue, 19 Aug 2014 15:25:49 +0000 (17:25 +0200)
committerMartin Baulig <martin.baulig@xamarin.com>
Mon, 25 Aug 2014 16:15:49 +0000 (18:15 +0200)
When the stream returned by WebClient.OpenWrite() / OpenWriteAsync() /
OpenWriteTaskAsync(), we need to call GetResponse() and read the full
response.

Unfortunately, there is no async API available for this, so this API should
not be used in async applications.

mcs/class/System/System.Net/WebClient.cs
mcs/class/System/System.Net/WebConnectionStream.cs

index fa2efeea8a4411877a6225789a5f58869b048eb4..ded7767114a62349033d4746f6f240ec534895cc 100644 (file)
@@ -408,7 +408,7 @@ namespace System.Net
                                SetBusy ();
                                async = false;
                                WebRequest request = SetupRequest (address, method, true);
-                               return request.GetRequestStream ();
+                               return OpenWriteStream (request);
                        } catch (WebException) {
                                throw;
                        } catch (Exception ex) {
@@ -419,6 +419,15 @@ namespace System.Net
                        }
                }
 
+               Stream OpenWriteStream (WebRequest request)
+               {
+                       var stream = request.GetRequestStream ();
+                       var wcs = stream as WebConnectionStream;
+                       if (wcs != null)
+                               wcs.GetResponseOnClose = true;
+                       return stream;
+               }
+
                private string DetermineMethod (Uri address, string method, bool is_upload)
                {
                        if (method != null)
@@ -1268,7 +1277,7 @@ namespace System.Net
                                        WebRequest request = null;
                                        try {
                                                request = SetupRequest ((Uri) args [0], (string) args [1], true);
-                                               Stream stream = request.GetRequestStream ();
+                                               var stream = OpenWriteStream (request);
                                                OnOpenWriteCompleted (
                                                        new OpenWriteCompletedEventArgs (stream, null, false, args [2]));
                                        } catch (ThreadInterruptedException){
@@ -1841,8 +1850,12 @@ namespace System.Net
                        try {
                                SetBusy ();
                                cts = new CancellationTokenSource ();
-                               request = SetupRequest (address);
-                               return await request.GetRequestStreamAsync ().ConfigureAwait (false);
+                               request = await SetupRequestAsync (address, method, true).ConfigureAwait (false);
+                               var stream = await request.GetRequestStreamAsync ();
+                               var wcs = stream as WebConnectionStream;
+                               if (wcs != null)
+                                       wcs.GetResponseOnClose = true;
+                               return stream;
                        } catch (WebException) {
                                throw;
                        } catch (OperationCanceledException) {
index b946654f329dfbf3bb9e78bfce8161dde8730c83..8ef558d72fd997d284c76319ee04b76159d0b7e6 100644 (file)
@@ -755,8 +755,22 @@ namespace System.Net
                        disposed = true;
                }
 
+               internal bool GetResponseOnClose {
+                       get; set;
+               }
+
                public override void Close ()
                {
+                       if (GetResponseOnClose) {
+                               if (disposed)
+                                       return;
+                               disposed = true;
+                               var response = (HttpWebResponse)request.GetResponse ();
+                               response.ReadAll ();
+                               response.Close ();
+                               return;
+                       }
+
                        if (sendChunked) {
                                if (disposed)
                                        return;