asp.nethttpserver-sent-eventskeep-aliveashx

Adding Connection: keep-alive header is not returned to client in ASP.net


Short Version

I'm adding the response header:

Connection: keep-alive

but it's not in the resposne.

Long Version

I am trying to add a header to an HttpResponse in ASP.net:

public void ProcessRequest(HttpContext context)
{
    context.Response.CacheControl = "no-cache";
    context.Response.AppendHeader("Connection", "keep-alive");
    context.Response.AppendHeader("AreTheseWorking", "yes");
    context.Response.Flush();
}

And when the response comes back to the client (e.g. Chrome, Edge, Internet Explorer, Postman), the Connection header is missing:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Transfer-Encoding: chunked
Expires: -1
Server: Microsoft-IIS/10.0
AreTheseWorking: yes
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sat, 26 Feb 2022 16:29:17 GMT

What am I doing wrong?

Bonus Chatter

In addition to trying AppendHeader:

context.Response.AppendHeader("Connection", "keep-alive"); //preferred

I also tried AddHeader (which exists "for compatibility with earlier versions of ASP"):

context.Response.AddHeader("Connection", "keep-alive"); // legacy

I also tried Headers.Add:

context.Response.Headers.Add("Connection", "keep-alive"); //requires IIS 7 and integrated pipeline

What am i doing wrong?

Bonus: hypothetical motivation for the question


Solution

  • By default keep-alive is not allowed in ASP.net.

    In order to allow it, you need to add an option to your web.config:

    web.config:

    <configuration>
        <system.webServer>
            <httpProtocol allowKeepAlive="true" />
        </system.webServer>
    </configuration>
    

    This is especially important for Server-Send Events:

    public void ProcessRequest(HttpContext context)
    {
       if (context.Request.AcceptTypes.Any("text/event-stream".Contains))
       {
          //Startup the HTTP Server Send Event - broadcasting values every 1 second.
          SendSSE(context);
          return;
       }
    }
    
    private void SendSSE(HttpContext context)
    {
       //Don't worry about it.
       string sessionId = context.Session.SessionID; //https://stackoverflow.com/a/1966562/12597
    
       //Setup the response the way SSE needs to be
       context.Response.ContentType = "text/event-stream";
       context.Response.CacheControl = "no-cache";
       context.Response.AppendHeader("Connection", "keep-alive");
       context.Response.Flush();
    
       while (context.Response.IsClientConnected)
       {
          System.Threading.Thread.Sleep(1000);
     
          String data = DateTime.Now.ToString();
          context.Response.Write("data: " + data + "\n\n");
          context.Response.Flush();
       }
    }