[System.Net.Http] Add Transfer-Encoding: chunked special handling. Fixes #47599
authorMarek Safar <marek.safar@gmail.com>
Tue, 14 Feb 2017 15:20:31 +0000 (16:20 +0100)
committerMarek Safar <marek.safar@gmail.com>
Wed, 15 Feb 2017 12:10:43 +0000 (13:10 +0100)
mcs/class/System.Net.Http/System.Net.Http/HttpClientHandler.cs
mcs/class/System.Net.Http/Test/System.Net.Http/HttpClientTest.cs
mcs/class/System/System.Net/HttpListenerRequest.cs

index a3335ea5506ffe67aafedba5773301d48b9cee77..e1cd94a05a43fc99c749f54ff51fc7398a0eaffe 100644 (file)
@@ -292,8 +292,9 @@ namespace System.Net.Http
                                }
 
                                if (header.Key == "Transfer-Encoding") {
-                                       // Chunked Transfer-Encoding is never set for HttpWebRequest. It's detected
-                                       // from ContentLength by HttpWebRequest
+                                       //
+                                       // Chunked Transfer-Encoding is set for HttpWebRequest later when Content length is checked
+                                       //
                                        values = values.Where (l => l != "chunked");
                                }
 
@@ -354,15 +355,22 @@ namespace System.Net.Http
                                                        }
                                                }
 
-                                               //
-                                               // Content length has to be set because HttpWebRequest is running without buffering
-                                               //
-                                               var contentLength = content.Headers.ContentLength;
-                                               if (contentLength != null) {
-                                                       wrequest.ContentLength = contentLength.Value;
+                                               if (request.Headers.TransferEncodingChunked == true) {
+                                                       wrequest.SendChunked = true;
                                                } else {
-                                                       await content.LoadIntoBufferAsync (MaxRequestContentBufferSize).ConfigureAwait (false);
-                                                       wrequest.ContentLength = content.Headers.ContentLength.Value;
+                                                       //
+                                                       // Content length has to be set because HttpWebRequest is running without buffering
+                                                       //
+                                                       var contentLength = content.Headers.ContentLength;
+                                                       if (contentLength != null) {
+                                                               wrequest.ContentLength = contentLength.Value;
+                                                       } else {
+                                                               if (MaxRequestContentBufferSize == 0)
+                                                                       throw new InvalidOperationException ("The content length of the request content can't be determined. Either set TransferEncodingChunked to true, load content into buffer, or set MaxRequestContentBufferSize.");
+
+                                                               await content.LoadIntoBufferAsync (MaxRequestContentBufferSize).ConfigureAwait (false);
+                                                               wrequest.ContentLength = content.Headers.ContentLength.Value;
+                                                       }
                                                }
 
                                                wrequest.ResendContentFactory = content.CopyTo;
index d9aab417dfa00762ff0848ae78385316ada5a7e3..72508c4883349ae19ada77271c939bfe18c04264 100644 (file)
@@ -1093,6 +1093,110 @@ namespace MonoTests.System.Net.Http
                        }
                }
 
+               [Test]
+#if FEATURE_NO_BSD_SOCKETS
+               [ExpectedException (typeof (PlatformNotSupportedException))]
+#endif
+               public void Post_TransferEncodingChunked ()
+               {
+                       bool? failed = null;
+                       var listener = CreateListener (l => {
+                               try {
+                                       var request = l.Request;
+
+                                       Assert.IsNull (request.AcceptTypes, "#1");
+                                       Assert.AreEqual (-1, request.ContentLength64, "#2");
+                                       Assert.IsNull (request.ContentType, "#3");
+                                       Assert.AreEqual (0, request.Cookies.Count, "#4");
+                                       Assert.IsTrue (request.HasEntityBody, "#5");
+                                       Assert.AreEqual (TestHost, request.Headers ["Host"], "#6b");
+                                       Assert.AreEqual ("POST", request.HttpMethod, "#7");
+                                       Assert.IsFalse (request.IsAuthenticated, "#8");
+                                       Assert.IsTrue (request.IsLocal, "#9");
+                                       Assert.IsFalse (request.IsSecureConnection, "#10");
+                                       Assert.IsFalse (request.IsWebSocketRequest, "#11");
+                                       Assert.IsTrue (request.KeepAlive, "#12");
+                                       Assert.AreEqual (HttpVersion.Version11, request.ProtocolVersion, "#13");
+                                       Assert.IsNull (request.ServiceName, "#14");
+                                       Assert.IsNull (request.UrlReferrer, "#15");
+                                       Assert.IsNull (request.UserAgent, "#16");
+                                       Assert.IsNull (request.UserLanguages, "#17");
+                                       Assert.AreEqual ("chunked", request.Headers ["Transfer-Encoding"], "#18");
+                                       Assert.IsNull (request.Headers ["Content-Length"], "#19");
+                                       failed = false;
+                               } catch (Exception e) {
+                                       failed = true;
+                                       Console.WriteLine (e);
+                               }
+                       });
+
+                       try {
+                               var client = new HttpClient ();
+
+                               client.DefaultRequestHeaders.TransferEncodingChunked = true;
+
+                               var imageContent = new StreamContent (new MemoryStream ());
+
+                               var response = client.PostAsync (LocalServer, imageContent).Result;
+
+                               Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "#101");
+                               Assert.AreEqual(false, failed, "#102");
+                       } finally {
+                               listener.Close ();
+                       }
+               }
+
+               [Test]
+#if FEATURE_NO_BSD_SOCKETS
+               [ExpectedException (typeof (PlatformNotSupportedException))]
+#endif
+               public void Post_StreamCaching ()
+               {
+                       bool? failed = null;
+                       var listener = CreateListener (l => {
+                               try {
+                                       var request = l.Request;
+
+                                       Assert.IsNull (request.AcceptTypes, "#1");
+                                       Assert.AreEqual (0, request.ContentLength64, "#2");
+                                       Assert.IsNull (request.ContentType, "#3");
+                                       Assert.AreEqual (0, request.Cookies.Count, "#4");
+                                       Assert.IsFalse (request.HasEntityBody, "#5");
+                                       Assert.AreEqual (TestHost, request.Headers ["Host"], "#6b");
+                                       Assert.AreEqual ("POST", request.HttpMethod, "#7");
+                                       Assert.IsFalse (request.IsAuthenticated, "#8");
+                                       Assert.IsTrue (request.IsLocal, "#9");
+                                       Assert.IsFalse (request.IsSecureConnection, "#10");
+                                       Assert.IsFalse (request.IsWebSocketRequest, "#11");
+                                       Assert.IsTrue (request.KeepAlive, "#12");
+                                       Assert.AreEqual (HttpVersion.Version11, request.ProtocolVersion, "#13");
+                                       Assert.IsNull (request.ServiceName, "#14");
+                                       Assert.IsNull (request.UrlReferrer, "#15");
+                                       Assert.IsNull (request.UserAgent, "#16");
+                                       Assert.IsNull (request.UserLanguages, "#17");
+                                       Assert.IsNull (request.Headers ["Transfer-Encoding"], "#18");
+                                       Assert.AreEqual ("0", request.Headers ["Content-Length"], "#19");
+                                       failed = false;
+                               } catch (Exception e) {
+                                       failed = true;
+                                       Console.WriteLine (e);
+                               }
+                       });
+
+                       try {
+                               var client = new HttpClient ();
+
+                               var imageContent = new StreamContent (new MemoryStream ());
+
+                               var response = client.PostAsync (LocalServer, imageContent).Result;
+
+                               Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "#101");
+                               Assert.AreEqual(false, failed, "#102");
+                       } finally {
+                               listener.Close ();
+                       }
+               }
+
                [Test]
                [Category ("MobileNotWorking")] // Missing encoding
 #if FEATURE_NO_BSD_SOCKETS
index a12aa233b71643e260d48e1ed79834390f9d6de0..fc0125df25a8fbd10362b6bfb2acea030bcdfde9 100644 (file)
@@ -404,7 +404,7 @@ namespace System.Net {
                }
 
                public long ContentLength64 {
-                       get { return content_length; }
+                       get { return is_chunked ? -1 : content_length; }
                }
 
                public string ContentType {