unosquare / embedio

A tiny, cross-platform, module based web server for .NET
http://unosquare.github.io/embedio
Other
1.45k stars 175 forks source link

Content-Length and HTTP Head requests #564

Open Warpten opened 2 years ago

Warpten commented 2 years ago

Describe the bug Content-Length being set through either of the following ways does not reflect on the response seen on the wire when executed from the handler of an HTTP HEAD request.

Response.ContentLength64 = ...;
Response.Headers.Set(HttpHeaderNames.ContentLength, ...)

To Reproduce Steps to reproduce the behavior:

  1. Compile the following program:

    internal class Program : WebApiController
    {
        static void Main(string[] args)
        {
            var server = new WebServer(o => {
                o.WithUrlPrefix("http://localhost:8080")
                    .WithMode(HttpListenerMode.EmbedIO);
            });
    
            server.WithWebApi("/", m => m.RegisterController<Program>());
    
            server.RunAsync();
            Console.ReadKey(true);
        }
    
        [Route(HttpVerbs.Head, "/hello/world")]
        public void Handle()
        {
            Response.Headers.Set(HttpHeaderNames.ContentLength, "12345");
            Response.ContentLength64 = 123;
        }
    }
  2. Send an HTTP HEAD request to http://localhost:8080/hello/world and notice that the Content-Length header in response is 0.
  3. Notice this bug does not happen with HttpListenerMode.Microsoft.

Expected behavior Content-Length should have the value assigned to it

Screenshots

Desktop (please complete the following information):

Additional context EmbedIO's built in default logger will correctly show the Content-Length in the log, but the value sent is wrong.

Something else to consider is that while calling SetLength on the response output stream throws an error (caught by EmbedIO), the value sent on the wire for Content-Length becomes correct. My guess is that it's a side-effect of the exception being thrown (which is expected).

Furthermore, EmbedIO should probably forbid operating on Response.OutputStream altogether from a HEAD request, since clients are expected to ignore the body of HEAD replies.

rdeago commented 2 years ago

Hello @Warpten, thanks for taking the time to report this twice - first on Slack, then here.

I've fixed the issue both in my version 4 work-in-SLOW-progress working copy and in a backport PR for version 3.

EmbedIO should probably forbid operating on Response.OutputStream altogether from a HEAD request

Interesting topic for a discussion 😉 (that can be later converted to a feature request).