aspnet / HttpAbstractions

[Archived] HTTP abstractions such as HttpRequest, HttpResponse, and HttpContext, as well as common web utilities. Project moved to https://github.com/aspnet/AspNetCore

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Closing chunked responses early via HttpResponse or HttpContext

hotchkj opened this issue · comments

Hi, hopefully this is the right place for this question. I'm implementing on-demand streaming of a zip download via chunked transfer (code below) in ASP.NET Core.

How do I close the chunked transfer early in the face of errors, such that a client can understand 'this transfer was interrupted'? I tried HttpContext.Abort and HttpResponse.Body.Dispose but that didn't seem to help. I always seem to have the browser consider the download complete (just corrupt) - testing happens to be on Firefox.

My understanding (and happy to be corrected if I'm wrong) is that the correct thing is to close the connection without sending the final terminating line - but I am not sure how to do that many levels above in ASP.NET. If it helps, our use-case is MVC Core on Kestrel, on top of ASP.NET Core on CentOS & Docker.

Example code inside an MVC action:

// Content-Disposition is an attachment, Content-Type: application/zip
using (var archive = new ZipArchive(new PositionPreservingWriteOnlyStream(_httpContextAccessor.HttpContext.Response.Body), ZipArchiveMode.Create, true))
{
	// If somewhere below throws, how to terminate the chunked transfer so the download is aborted?
	foreach (var source in sources)
	{
		var fileEntry = archive.CreateEntry(source.Path, CompressionLevel.Optimal);
		using (var zipEntryStream = fileEntry.Open())
		{
			await source.StreamInto(zipEntryStream, ct).ConfigureAwait(false);
		}
	}
}

Thanks in advance for assistance.

HttpContext.Abort() is the correct approach, or just throwing an unhandled exception and letting the server abort. Are you sure the client receives the chunk terminator? A missing terminator displays differently in the various browsers. What does Fiddler or a network trace show?

There was a bug in older versions of AspNetCoreModule (IIS) that would mistakenly add the chunked terminator for failed responses.

Clearly I needed to dig deeper before raising this issue 😊. Turns out I had misread the tracing before (too many 0x0d 0x0a values stared at...), and testing in more browsers does show the download as failed. It seems to be a peculiar quirk of Firefox to list the download as completed, but Chrome lists Network Failure explicitly.

Regardless, much appreciated for the fast confirmation that HttpContext.Abort() is the right approach to use. Thanks very much!