Merge pull request #954 from ermshiperete/bug-xamarin-8907
[mono.git] / mcs / class / System / System.Net / HttpWebRequest.cs
index cbf075efa42019e2723f10ae84524c56507b990d..cfee23914781152e6a143f5b8acb89cb8b67f8c0 100644 (file)
@@ -56,6 +56,7 @@ namespace System.Net
                bool allowBuffering = true;
                X509CertificateCollection certificates;
                string connectionGroup;
+               bool haveContentLength;
                long contentLength = -1;
                HttpContinueDelegate continueDelegate;
                CookieContainer cookieContainer;
@@ -277,6 +278,7 @@ namespace System.Net
                                        throw new ArgumentOutOfRangeException ("value", "Content-Length must be >= 0");
                                        
                                contentLength = value;
+                               haveContentLength = true;
                        }
                }
                
@@ -1109,8 +1111,15 @@ namespace System.Net
                        if (continueDelegate != null)
                                continueDelegate (statusCode, headers);
                }
+
+               void RewriteRedirectToGet ()
+               {
+                       method = "GET";
+                       webHeaders.RemoveInternal ("Transfer-Encoding");
+                       sendChunked = false;
+               }
                
-               bool Redirect (WebAsyncResult result, HttpStatusCode code)
+               bool Redirect (WebAsyncResult result, HttpStatusCode code, WebResponse response)
                {
                        redirects++;
                        Exception e = null;
@@ -1122,12 +1131,12 @@ namespace System.Net
                        case HttpStatusCode.MovedPermanently: // 301
                        case HttpStatusCode.Redirect: // 302
                                if (method == "POST")
-                                       method = "GET";
+                                       RewriteRedirectToGet ();
                                break;
                        case HttpStatusCode.TemporaryRedirect: // 307
                                break;
                        case HttpStatusCode.SeeOther: //303
-                               method = "GET";
+                               RewriteRedirectToGet ();
                                break;
                        case HttpStatusCode.NotModified: // 304
                                return false;
@@ -1140,12 +1149,13 @@ namespace System.Net
                                break;
                        }
 
+                       if (method != "GET" && !InternalAllowBuffering)
+                               e = new WebException ("The request requires buffering data to succeed.", null, WebExceptionStatus.ProtocolError, webResponse);
+
                        if (e != null)
                                throw e;
 
                        contentLength = -1;
-                       //bodyBufferLength = 0;
-                       //bodyBuffer = null;
                        uriString = webResponse.Headers ["Location"];
 
                        if (uriString == null)
@@ -1175,12 +1185,15 @@ namespace System.Net
                        } else if (contentLength != -1) {
                                if (auth_state.NtlmAuthState == NtlmAuthState.Challenge || proxy_auth_state.NtlmAuthState == NtlmAuthState.Challenge) {
                                        // We don't send any body with the NTLM Challenge request.
-                                       webHeaders.SetInternal ("Content-Length", "0");
+                                       if (haveContentLength || gotRequestStream || contentLength > 0)
+                                               webHeaders.SetInternal ("Content-Length", "0");
+                                       else
+                                               webHeaders.RemoveInternal ("Content-Length");
                                } else {
                                        if (contentLength > 0)
                                                continue100 = true;
 
-                                       if (gotRequestStream || contentLength > 0)
+                                       if (haveContentLength || gotRequestStream || contentLength > 0)
                                                webHeaders.SetInternal ("Content-Length", contentLength.ToString ());
                                }
                                webHeaders.RemoveInternal ("Transfer-Encoding");
@@ -1518,6 +1531,11 @@ namespace System.Net
                                                r.SetCompleted (false, webResponse);
                                                r.DoCallback ();
                                        } else {
+                                               if (sendChunked) {
+                                                       sendChunked = false;
+                                                       webHeaders.RemoveInternal ("Transfer-Encoding");
+                                               }
+
                                                if (webResponse != null) {
                                                        if (HandleNtlmAuth (r))
                                                                return;
@@ -1652,11 +1670,7 @@ namespace System.Net
                                        if (!usedPreAuth && CheckAuthorization (webResponse, code)) {
                                                // Keep the written body, so it can be rewritten in the retry
                                                if (InternalAllowBuffering) {
-                                                       // NTLM: This is to avoid sending data in the 'challenge' request
-                                                       // We save it in the first request (first 401), don't send anything
-                                                       // in the challenge request and send it in the response request along
-                                                       // with the buffers kept form the first request.
-                                                       if (auth_state.NtlmAuthState == NtlmAuthState.Challenge || proxy_auth_state.NtlmAuthState == NtlmAuthState.Challenge) {
+                                                       if (writeStream.WriteBufferLength > 0) {
                                                                bodyBuffer = writeStream.WriteBuffer;
                                                                bodyBufferLength = writeStream.WriteBufferLength;
                                                        }
@@ -1703,7 +1717,7 @@ namespace System.Net
                                bool b = false;
                                int c = (int) code;
                                if (allowAutoRedirect && c >= 300) {
-                                       b = Redirect (result, code);
+                                       b = Redirect (result, code, webResponse);
                                        if (InternalAllowBuffering && writeStream.WriteBufferLength > 0) {
                                                bodyBuffer = writeStream.WriteBuffer;
                                                bodyBufferLength = writeStream.WriteBufferLength;