Http chunk encoding miss end of chunked encoding("0\r\n") or tailer("\r\n") on IIS 7.5

linq.x 6 Reputation points
2023-03-22T09:35:26.2833333+00:00

I create a simple ASP .NET Application and write a generic web handler (HelloFilterWithClose.ashx).

HelloFilterWithClose.ashx ProcessRequest with setting a HttpResponse.Filter(MyFilter), and it response to http client with write a PDF file to http body. After writing a PDF file to http body, it Flush and Close HttpResponse.

Running the app on IIS 7.5 Windows Server 2008 R2 sets the transfer encoding of the response to chunked and Wireshark shows that there is only one data chunk but no end of chunked encoding("0\r\n") or tailer("\r\n")

Running the app on IIS 10 will have no above problem.

MyFilter:


    public class MyFilter : Stream
    {
        private Stream m_stream;

        public MyFilter(Stream stream)
        {
            m_stream = stream;
        }

        public override bool CanRead
        {
            get { return m_stream.CanRead; }
        }

        public override bool CanSeek
        {
            get { return m_stream.CanSeek; }
        }

        public override bool CanWrite
        {
            get { return m_stream.CanWrite; }
        }

        public override long Length
        {
            get { return m_stream.Length; }
        }

        public override long Position
        {
            get
            {
                return m_stream.Position;
            }
            set
            {
                m_stream.Position = value;
            }
        }

        public override void Close()
        {
            m_stream.Close();
        }
        public override void Flush()
        {
            m_stream.Flush();
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            return m_stream.Read(buffer, offset, count);
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            return m_stream.Seek(offset, origin);
        }

        public override void SetLength(long value)
        {
            m_stream.SetLength(value);
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            m_stream.Write(buffer, offset, count);
        }
    }

HelloFilterWithClose.ashx:


    public class HelloFilterWithClose : IHttpHandler
    {
        public void SimpleRequest(HttpContext context)
        {
            context.Response.BufferOutput = false;
            context.Response.ContentType = "application/octet-stream";
            context.Response.AddHeader("Content-Disposition", "attachment;FileName=filterWithClose.pdf");
            context.Response.AddHeader("Content-Length", "32038");
            context.Response.WriteFile("hello.pdf");
            context.Response.Flush();
            context.Response.Close();
        }
        private void SetFilter(HttpContext context)
        {

            HttpResponse response = context.Response;
            Stream filterStream = response?.Filter;
            if (null == filterStream)
            {
                return;
            }
            response.Filter = new MyFilter(filterStream);
        }
        public void ProcessRequest(HttpContext context)
        {
            SetFilter(context);
            SimpleRequest(context);
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }

End

Internet Information Services
ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,288 questions
{count} votes

1 answer

Sort by: Most helpful
  1. AgaveJoe 26,146 Reputation points
    2023-03-23T13:25:21.9+00:00

    The chunked encoding specifications are below. As far as I can tell, the design you've shared does not consider the chunked encoding specifications.

    https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding

    Data is sent in a series of chunks. The Content-Length header is omitted in this case and at the beginning of each chunk you need to add the length of the current chunk in hexadecimal format, followed by '\r\n' and then the chunk itself, followed by another '\r\n'. The terminating chunk is a regular chunk, with the exception that its length is zero. It is followed by the trailer, which consists of a (possibly empty) sequence of header fields.