Disable response buffering via the IHttpBufferingFeature (#379)

* Disable response buffering via the IHttpBufferingFeature
- To make sure SignalR works with servers and middleware
that do perform response buffering, disable it via the
IHttpBufferingFeature for SSE.
- Added test to verify buffering is disabled
This commit is contained in:
David Fowler 2017-04-10 19:05:06 -07:00 committed by GitHub
parent 4c183b4d00
commit 0546dc21f4
2 changed files with 41 additions and 0 deletions

View File

@ -9,6 +9,7 @@ using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Channels;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Sockets.Internal.Formatters;
using Microsoft.Extensions.Logging;
@ -29,6 +30,11 @@ namespace Microsoft.AspNetCore.Sockets.Transports
{
context.Response.ContentType = "text/event-stream";
context.Response.Headers["Cache-Control"] = "no-cache";
// Make sure we disable all response buffering for SSE
var bufferingFeature = context.Features.Get<IHttpBufferingFeature>();
bufferingFeature?.DisableResponseBuffering();
context.Response.Headers["Content-Encoding"] = "identity";
await context.Response.Body.FlushAsync();

View File

@ -1,12 +1,14 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.IO.Pipelines;
using System.Text;
using System.Threading.Tasks;
using System.Threading.Tasks.Channels;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Sockets.Transports;
using Microsoft.Extensions.Logging;
using Xunit;
@ -30,6 +32,22 @@ namespace Microsoft.AspNetCore.Sockets.Tests
Assert.Equal("no-cache", context.Response.Headers["Cache-Control"]);
}
[Fact]
public async Task SSETurnsResponseBufferingOff()
{
var channel = Channel.CreateUnbounded<Message>();
var context = new DefaultHttpContext();
var feature = new HttpBufferingFeature();
context.Features.Set<IHttpBufferingFeature>(feature);
var sse = new ServerSentEventsTransport(channel, new LoggerFactory());
Assert.True(channel.Out.TryComplete());
await sse.ProcessRequestAsync(context, context.RequestAborted);
Assert.True(feature.ResponseBufferingDisabled);
}
[Theory]
[InlineData("Hello World", "data: T\r\ndata: Hello World\r\n\r\n")]
[InlineData("Hello\nWorld", "data: T\r\ndata: Hello\r\ndata: World\r\n\r\n")]
@ -53,5 +71,22 @@ namespace Microsoft.AspNetCore.Sockets.Tests
Assert.Equal(expected, Encoding.UTF8.GetString(ms.ToArray()));
}
private class HttpBufferingFeature : IHttpBufferingFeature
{
public bool RequestBufferingDisabled { get; set; }
public bool ResponseBufferingDisabled { get; set; }
public void DisableRequestBuffering()
{
RequestBufferingDisabled = true;
}
public void DisableResponseBuffering()
{
ResponseBufferingDisabled = true;
}
}
}
}