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:
parent
4c183b4d00
commit
0546dc21f4
|
|
@ -9,6 +9,7 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks.Channels;
|
using System.Threading.Tasks.Channels;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Sockets.Internal.Formatters;
|
using Microsoft.AspNetCore.Sockets.Internal.Formatters;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
|
@ -29,6 +30,11 @@ namespace Microsoft.AspNetCore.Sockets.Transports
|
||||||
{
|
{
|
||||||
context.Response.ContentType = "text/event-stream";
|
context.Response.ContentType = "text/event-stream";
|
||||||
context.Response.Headers["Cache-Control"] = "no-cache";
|
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";
|
context.Response.Headers["Content-Encoding"] = "identity";
|
||||||
|
|
||||||
await context.Response.Body.FlushAsync();
|
await context.Response.Body.FlushAsync();
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// 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.
|
// 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;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks.Channels;
|
using System.Threading.Tasks.Channels;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Http.Features;
|
||||||
using Microsoft.AspNetCore.Sockets.Transports;
|
using Microsoft.AspNetCore.Sockets.Transports;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -30,6 +32,22 @@ namespace Microsoft.AspNetCore.Sockets.Tests
|
||||||
Assert.Equal("no-cache", context.Response.Headers["Cache-Control"]);
|
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]
|
[Theory]
|
||||||
[InlineData("Hello World", "data: T\r\ndata: Hello World\r\n\r\n")]
|
[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")]
|
[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()));
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue