ASP.NET Web Interface: PushStreamContent compression is not flushed
I am using PushStreamContent
ASP.NET Web API to move events from server to client (using Server-Sent events). After every event dispatched, I call Flush
in Stream
to send the buffer data to the client. However, I noticed that flushing is not always (always). Sometimes some of the data is sent to the client, and the rest is sent when the next event is recorded (which might happen after a few seconds).
Here's some sample code:
public class MyController : ApiController
{
private static readonly string[] LineSeparators
= new[] { Environment.NewLine };
public HttpResponseMessage GetData(string id)
{
var response = Request.CreateResponse();
response.Content = new PushStreamContent(
new Func<Stream, HttpContent, TransportContext, Task>(StartStream),
new MediaTypeHeaderValue("text/event-stream") { CharSet = "UTF-8" });
return response;
}
private async Task StartStream(Stream outputStream, HttpContent content, TransportContext context)
{
using (outputStream)
using (var writer = new StreamWriter(outputStream, new UTF8Encoding(false)))
{
writer.NewLine = "\n";
while (true)
{
WriteEvent(writer, "ping", DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture));
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
}
private static void WriteEvent(TextWriter writer, string eventType, string data)
{
writer.WriteLine("event:" + eventType);
writer.WriteLine("data:" + data);
writer.WriteLine();
writer.Flush(); // StreamWriter.Flush calls Flush on underlying Stream
}
}
How do I disable data buffering or force data flushing?
source to share
The source of the problem is stream cleaning.
In the sample code, you deform the original stream with a StreamWriter and then clean up the StreamWriter.
You also need to clean up the original stream:
private async Task StartStream(Stream outputStream, HttpContent content, TransportContext context)
{
using (outputStream)
using (var writer = new StreamWriter(outputStream, new UTF8Encoding(false)))
{
writer.NewLine = "\n";
while (true)
{
WriteEvent(writer, "ping", DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture));
outputStream.Flush();
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
}
source to share
After spending a full day figuring out what the problem was and HttpSelfHostServer
before (desperately) giving out the award, I found that the problem was with what I was using HttpSelfHostServer
and HttpSelfHostServer
needed to be tuned TransferMode = TransferMode.Streamed
to HttpSelfHostConfiguration
. All this.
source to share