Skip to content

HttpWebRequest.AllowWriteStreamBuffering seems to lack an implementation #60993

Closed
@logiclrd

Description

@logiclrd

Description

There is a properly on HttpWebRequest called AllowWriteStreamBuffering. However, setting it doesn't seem to have any effect; the request body is still buffered to a MemoryStream before the request is sent. This makes it rather difficult to do things like upload massive files via HTTP PUT or POST.

The following comment seems to indicate that the functionality of unbuffered write streams, as originally implemented in the .NET Framework, was torn out of the code as part of .NET Core development because .NET Core's HttpWebRequest lacked an AllowWriteStreamBuffering:

// Cache the request stream into a MemoryStream. This is the
// default behavior of Desktop HttpWebRequest.AllowWriteStreamBuffering (true).
// Unfortunately, this property is not exposed in .NET Core, so it can't be changed
// This will result in inefficient memory usage when sending (POST'ing) large
// amounts of data to the server such as from a file stream.

...and then it was never reintroduced, even though the property was reintroduced in .NET Core 2.0 (according to the documentation).

In my testing, running against .NET 5.0, extremely large files cannot be transferred at all, because regardless of the value of AllowWriteStreamBuffering, trying to write them to the request body stream produces the following exception:

System.IO.IOException: Stream was too long.

This is an exception produced by the MemoryStream class.

Reproduction Steps

			var request = (HttpWebRequest)WebRequest.Create("https://google.com/test"); // exact URL is irrelevant because request never gets that far

			request.AllowWriteStreamBuffering = false;
			request.Method = "PUT";

			using (var requestStream = request.GetRequestStream())
			{
				byte[] buffer = new byte[1048576];

				for (int megabyte = 0; megabyte < 2048; megabyte++)
					requestStream.Write(buffer, 0, buffer.Length);
			}

Expected behavior

The above sample should actually connect to Google and try to send 2 GB of zeroes (don't do this :-) ).

Actual behavior

No connection at all is made because GetRequestStream actually just creates a MemoryStream under the hood to buffer the full request body, even though AllowWriteStreamBuffering is false.

Regression?

I am reasonably confident that this code works properly in the full .NET Framework right up to version 4.8.

Known Workarounds

No response

Configuration

I need to run more testing to confirm, but I believe the bug reproduces on all .NET Core versions, as well as .NET 5.0 and .NET 6 prereleases. The bug does not reproduce on any .NET Framework version, right up to 4.8.

Other information

No response

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions