Skip to content

Instantly share code, notes, and snippets.

@Dkowald
Last active January 22, 2019 15:33
Show Gist options
  • Save Dkowald/28ea6f6bd38562c131a76052587c6268 to your computer and use it in GitHub Desktop.
Save Dkowald/28ea6f6bd38562c131a76052587c6268 to your computer and use it in GitHub Desktop.
ResponseBuffering for Asp.Net core
using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
// ReSharper disable once CheckNamespace
namespace kwd.gist
{
/// <summary>
/// Middleware to capture response stream so it can be
/// manipulated further.
/// </summary>
/// <remarks>
/// Useful to capture HTTP response for further processing, rather than immediately sending response.
/// </remarks>
public class ResponseBuffering : IMiddleware
{
private Stream _original;
private MemoryStream _buffered;
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
if (context.Response.HasStarted)
{
throw new Exception("Cannot buffer response, it has already started");
}
_original = context.Response.Body;
_buffered = new MemoryStream();
context.Items.Add(nameof(ResponseBuffering), _buffered);
context.Response.Body = _buffered;
await next(context);
if (_buffered != null)
{
_buffered.Seek(0, SeekOrigin.Begin);
context.Response.Body = _original;
await _buffered.CopyToAsync(context.Response.Body);
_buffered.Dispose();
_buffered = null;
}
}
}
}
using System.IO;
using System.Text;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
// ReSharper disable once CheckNamespace
namespace kwd.gist
{
/// <summary>
/// Various extensions to add and use the <see cref="ResponseBuffering"/> middleware.
/// </summary>
public static class ResponseBufferingMiddlewareExtensions
{
/// <summary>
/// Add the <see cref="ResponseBuffering"/> middleware to the container.
/// </summary>
public static IServiceCollection AddResponseBuffering(this IServiceCollection services)
{
services.AddScoped<ResponseBuffering>();
return services;
}
/// <summary>
/// Add the <see cref="ResponseBuffering"/> middleware to the Asp.Net pipeline.
/// </summary>
public static IApplicationBuilder UseResponseBuffering(this IApplicationBuilder builder)
{
builder.UseMiddleware<ResponseBuffering>();
return builder;
}
/// <summary>
/// True if the HTTP response output Body stream is being buffered.
/// </summary>
public static bool IsBuffered(this HttpResponse resp) =>
resp.Body is MemoryStream;
/// <summary>
/// True if current request context has a response that is buffered.
/// </summary>
public static bool IsResponseBuffered(this HttpContext ctx) =>
ctx?.Response?.IsBuffered() == true;
/// <summary>
/// Read current buffered response data (if any).
/// </summary>
public static string ReadBufferedResponse(this HttpContext ctx) =>
ReadBufferedResponse(ctx?.Response);
/// <summary>
/// Read current buffered response data (if any).
/// </summary>
public static string ReadBufferedResponse(this HttpResponse resp)
{
string result = null;
if (resp?.Body is MemoryStream mem)
{
var originalPosition = mem.Position;
mem.Position = 0;
using (var strStream = new StreamReader(mem, Encoding.UTF8, true, 1024, true))
{
result = strStream.ReadToEnd();
}
mem.Position = originalPosition;
}
return result;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment