Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache HTML and bypass controller completely #64

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public ContentfulContentService(
var pages = new QueryBuilder<Page>()
.ContentTypeIs(Page.ContentType)
.FieldEquals(c => c.Slug, slug)
.Include(5)
.Include(4)
.Limit(1);

var pageEntries = await _contentfulClient.GetEntries(pages);
Expand Down Expand Up @@ -56,7 +56,7 @@ public ContentfulContentService(
{
var config = new QueryBuilder<ContentfulConfigurationEntity>()
.ContentTypeIs(ContentfulConfigurationEntity.ContentType)
.Include(5)
.Include(2)
.Limit(1);

var configEntries = await _contentfulClient.GetEntries(config);
Expand Down
7 changes: 2 additions & 5 deletions src/web/CareLeavers.Web/Controllers/ContentfulController.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
using System.Diagnostics.CodeAnalysis;
using System.Text;
using System.Xml.Linq;
using CareLeavers.Web.Configuration;
using CareLeavers.Web.Contentful;
using Contentful.Core.Configuration;
using CareLeavers.Web.Filters;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Formatting = Newtonsoft.Json.Formatting;

namespace CareLeavers.Web.Controllers;

Expand Down Expand Up @@ -41,6 +37,7 @@ public async Task<IActionResult> GetContentAsJson(string slug, [FromServices] IW
}

[Route("/{**slug}")]
[ContentfulCaching]
public async Task<IActionResult> GetContent(string slug)
{
var page = await contentService.GetPage(slug);
Expand Down
76 changes: 76 additions & 0 deletions src/web/CareLeavers.Web/Filters/ContentfulCachingAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System.Text;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Caching.Distributed;

namespace CareLeavers.Web.Filters;

public class ContentfulCaching : ActionFilterAttribute
{
private MemoryStream? _memoryStream;
private Stream? _originalBodyStream;

public override async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next)
{
_memoryStream = null;
_originalBodyStream = null;

var distributedCache = context.HttpContext.RequestServices.GetRequiredService<IDistributedCache>();

var slug = context.RouteData.Values["slug"]?.ToString();

if (slug == null)
{
await base.OnActionExecutionAsync(context, next);
return;
}

var cachedResponse = await distributedCache.GetAsync($"contentful:html:{slug}");

if (cachedResponse != null)
{
context.Result = new ContentResult
{
Content = Encoding.UTF8.GetString(cachedResponse),
ContentType = "text/html"
};

return;
}

_memoryStream = new MemoryStream();
_originalBodyStream = context.HttpContext.Response.Body;
context.HttpContext.Response.Body = _memoryStream;

await base.OnActionExecutionAsync(context, next);
}

public override async Task OnResultExecutionAsync(
ResultExecutingContext context,
ResultExecutionDelegate next)
{
await base.OnResultExecutionAsync(context, next);

var slug = context.RouteData.Values["slug"]?.ToString();

if (slug == null || _memoryStream == null || _originalBodyStream == null)
{
return;
}

var distributedCache = context.HttpContext.RequestServices.GetRequiredService<IDistributedCache>();

_memoryStream.Seek(0, SeekOrigin.Begin);

var responseBody = await new StreamReader(_memoryStream).ReadToEndAsync();

_memoryStream.Seek(0, SeekOrigin.Begin);

context.HttpContext.Response.Body = _originalBodyStream!;
await context.HttpContext.Response.Body!.WriteAsync(_memoryStream.ToArray());

await distributedCache.SetAsync($"contentful:html:{slug}", Encoding.UTF8.GetBytes(responseBody));
}
}
2 changes: 1 addition & 1 deletion src/web/CareLeavers.Web/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"ShowCookieBanner": true
},
"Caching": {
"Type": "None",
"Type": "Memory",
"ConnectionString": "",
"Duration": "30.00:00:00"
},
Expand Down
Loading