diff --git a/sdk/core/Azure.Core/CHANGELOG.md b/sdk/core/Azure.Core/CHANGELOG.md index d061341fadb85..42ab8395ac180 100644 --- a/sdk/core/Azure.Core/CHANGELOG.md +++ b/sdk/core/Azure.Core/CHANGELOG.md @@ -7,6 +7,7 @@ ### Fixed - The race condition in `AzureEventSourceListener` class that sometimes resulted in a `NullReferenceException` in the `EventSource`. +- The overflow exception when content length is larger than `int.MaxValue`. ## 1.5.1 (2020-10-01) diff --git a/sdk/core/Azure.Core/src/Pipeline/HttpWebRequestTransport.cs b/sdk/core/Azure.Core/src/Pipeline/HttpWebRequestTransport.cs index 1187a2c711015..92a23144299a4 100644 --- a/sdk/core/Azure.Core/src/Pipeline/HttpWebRequestTransport.cs +++ b/sdk/core/Azure.Core/src/Pipeline/HttpWebRequestTransport.cs @@ -106,11 +106,12 @@ private HttpWebRequest CreateRequest(Request messageRequest) var request = WebRequest.CreateHttp(messageRequest.Uri.ToUri()); request.Method = messageRequest.Method.Method; request.Proxy = _proxy; + foreach (var messageRequestHeader in messageRequest.Headers) { if (string.Equals(messageRequestHeader.Name, HttpHeader.Names.ContentLength, StringComparison.OrdinalIgnoreCase)) { - request.ContentLength = int.Parse(messageRequestHeader.Value, CultureInfo.InvariantCulture); + request.ContentLength = long.Parse(messageRequestHeader.Value, CultureInfo.InvariantCulture); continue; } @@ -180,6 +181,12 @@ private HttpWebRequest CreateRequest(Request messageRequest) request.Headers.Add(messageRequestHeader.Name, messageRequestHeader.Value); } + if (request.ContentLength != -1) + { + // disable buffering when the content length is known + // as the content stream is re-playable and we don't want to allocate extra buffers + request.AllowWriteStreamBuffering = false; + } return request; } diff --git a/sdk/core/Azure.Core/tests/TestServer.cs b/sdk/core/Azure.Core/tests/TestServer.cs index 2853e6b1ead0a..0d9229597e7a9 100644 --- a/sdk/core/Azure.Core/tests/TestServer.cs +++ b/sdk/core/Azure.Core/tests/TestServer.cs @@ -29,7 +29,11 @@ public TestServer(RequestDelegate app) { _app = app; _host = new WebHostBuilder() - .UseKestrel(options => options.Listen(new IPEndPoint(IPAddress.Loopback, 0))) + .UseKestrel(options => + { + options.Limits.MaxRequestBodySize = null; + options.Listen(new IPEndPoint(IPAddress.Loopback, 0)); + }) .ConfigureServices(services => { services.AddSingleton(this); diff --git a/sdk/core/Azure.Core/tests/TransportFunctionalTests.cs b/sdk/core/Azure.Core/tests/TransportFunctionalTests.cs index 8e3cdc2e01e34..dc39216c0346f 100644 --- a/sdk/core/Azure.Core/tests/TransportFunctionalTests.cs +++ b/sdk/core/Azure.Core/tests/TransportFunctionalTests.cs @@ -94,6 +94,35 @@ public async Task SettingHeaderOverridesDefaultContentLength() Assert.AreEqual(50, contentLength); } + [Test] + public async Task CanSetContentLenghtOverMaxInt() + { + long contentLength = 0; + using TestServer testServer = new TestServer( + context => + { + contentLength = context.Request.ContentLength.Value; + }); + + var requestContentLength = long.MaxValue; + var transport = GetTransport(); + Request request = transport.CreateRequest(); + request.Method = RequestMethod.Post; + request.Uri.Reset(testServer.Address); + request.Content = RequestContent.Create(new byte[10]); + request.Headers.Add("Content-Length", requestContentLength.ToString()); + + try + { + await ExecuteRequest(request, transport); + } + catch (Exception) + { + // Sending the request would fail because of length mismatch + } + + Assert.AreEqual(requestContentLength, requestContentLength); + } [Test] public async Task HostHeaderSetFromUri()