Add SocketsHttpHandler check for TransferEncodingChunked w/o Content (dotnet/corefx...
authorStephen Toub <stoub@microsoft.com>
Sun, 11 Feb 2018 17:19:03 +0000 (12:19 -0500)
committerGitHub <noreply@github.com>
Sun, 11 Feb 2018 17:19:03 +0000 (12:19 -0500)
Commit migrated from https://github.com/dotnet/corefx/commit/bf5a3183bc901723ebe0bb3d178bec86cda57429

src/libraries/System.Net.Http/src/System/Net/Http/CurlHandler/CurlHandler.cs
src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/SocketsHttpHandler.cs
src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.cs

index 05530ae..85bba6b 100644 (file)
@@ -461,7 +461,9 @@ namespace System.Net.Http
 
             if (request.Headers.TransferEncodingChunked.GetValueOrDefault() && (request.Content == null))
             {
-                throw new InvalidOperationException(SR.net_http_chunked_not_allowed_with_empty_content);
+                return Task.FromException<HttpResponseMessage>(
+                    new HttpRequestException(SR.net_http_client_execution_error,
+                        new InvalidOperationException(SR.net_http_chunked_not_allowed_with_empty_content)));
             }
 
             if (_useCookies && _cookieContainer == null)
index 05a73c2..10b39f3 100644 (file)
@@ -264,17 +264,35 @@ namespace System.Net.Http
             CheckDisposed();
             HttpMessageHandler handler = _handler ?? SetupHandlerChain();
 
+            Exception error = ValidateAndNormalizeRequest(request);
+            if (error != null)
+            {
+                return Task.FromException<HttpResponseMessage>(error);
+            }
+
+            return handler.SendAsync(request, cancellationToken);
+        }
+
+        private Exception ValidateAndNormalizeRequest(HttpRequestMessage request)
+        {
             if (request.Version.Major == 0)
             {
-                return Task.FromException<HttpResponseMessage>(new NotSupportedException(SR.net_http_unsupported_version));
+                return new NotSupportedException(SR.net_http_unsupported_version);
             }
 
             // Add headers to define content transfer, if not present
-            if (request.Content != null &&
-                (!request.HasHeaders || request.Headers.TransferEncodingChunked != true) &&
-                request.Content.Headers.ContentLength == null)
+            bool transferEncodingChunkedSet = request.HasHeaders && request.Headers.TransferEncodingChunked.GetValueOrDefault();
+            if (request.Content == null)
+            {
+                if (transferEncodingChunkedSet)
+                {
+                    return new HttpRequestException(SR.net_http_client_execution_error,
+                        new InvalidOperationException(SR.net_http_chunked_not_allowed_with_empty_content));
+                }
+            }
+            else if (!transferEncodingChunkedSet && request.Content.Headers.ContentLength == null)
             {
-                // We have content, but neither Transfer-Encoding or Content-Length is set.
+                // We have content, but neither Transfer-Encoding nor Content-Length is set.
                 request.Headers.TransferEncodingChunked = true;
             }
 
@@ -283,7 +301,7 @@ namespace System.Net.Http
                 // HTTP 1.0 does not support chunking
                 if (request.Headers.TransferEncodingChunked == true)
                 {
-                    return Task.FromException<HttpResponseMessage>(new NotSupportedException(SR.net_http_unsupported_chunking));
+                    return new NotSupportedException(SR.net_http_unsupported_chunking);
                 }
 
                 // HTTP 1.0 does not support Expect: 100-continue; just disable it.
@@ -293,7 +311,7 @@ namespace System.Net.Http
                 }
             }
 
-            return handler.SendAsync(request, cancellationToken);
+            return null;
         }
     }
 }
index 6af8979..8037855 100644 (file)
@@ -1339,6 +1339,24 @@ namespace System.Net.Http.Functional.Tests
             });
         }
 
+        [Fact]
+        public async Task SendAsync_TransferEncodingSetButNoRequestContent_Throws()
+        {
+            if (IsNetfxHandler)
+            {
+                // no exception thrown
+                return;
+            }
+
+            var req = new HttpRequestMessage(HttpMethod.Post, "http://bing.com");
+            req.Headers.TransferEncodingChunked = true;
+            using (HttpClient c = CreateHttpClient())
+            {
+                HttpRequestException error = await Assert.ThrowsAsync<HttpRequestException>(() => c.SendAsync(req));
+                Assert.IsType<InvalidOperationException>(error.InnerException);
+            }
+        }
+
         [OuterLoop] // TODO: Issue #11345
         [Fact]
         public async Task GetAsync_ResponseHeadersRead_ReadFromEachIterativelyDoesntDeadlock()