From 667baa7354448e5e7e4931db42266b17215a4eb1 Mon Sep 17 00:00:00 2001 From: p-kaczynski Date: Thu, 26 Sep 2024 14:41:33 +0100 Subject: [PATCH] Add vary heade to flat and hierarchical collection GETs --- .../Integration/GetCollectionTests.cs | 29 +++++++++++++++++++ .../API/Features/Storage/StorageController.cs | 11 ++++--- .../Filters/VaryHeaderAttribute.cs | 15 ++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 src/IIIFPresentation/API/Infrastructure/Filters/VaryHeaderAttribute.cs diff --git a/src/IIIFPresentation/API.Tests/Integration/GetCollectionTests.cs b/src/IIIFPresentation/API.Tests/Integration/GetCollectionTests.cs index 3cfce24..373c8f5 100644 --- a/src/IIIFPresentation/API.Tests/Integration/GetCollectionTests.cs +++ b/src/IIIFPresentation/API.Tests/Integration/GetCollectionTests.cs @@ -59,6 +59,19 @@ public async Task Get_ChildHierarchical_Returns_Child() var firstItem = (Collection)collection.Items[0]; firstItem.Id.Should().Be("http://localhost/1/first-child/second-child"); } + + [Fact] + public async Task Get_ChildHierarchical_Returns_Vary_Header() + { + // Act + var response = await httpClient.GetAsync("1/first-child"); + + var collection = await response.ReadAsIIIFJsonAsync(); + + // Assert + response.StatusCode.Should().Be(HttpStatusCode.OK); + response.Headers.Vary.Should().HaveCount(2); + } [Fact] public async Task Get_Hierarchical_Redirects_WhenAuthAndShowExtrasHeaders() @@ -373,4 +386,20 @@ public async Task Get_ChildFlat_IgnoresOrderBy_WhenCalledWithInvalidOrderBy() collection.Items!.Count.Should().Be(1); collection.Items.OfType().First().Id.Should().Be("http://localhost/1/collections/FirstChildCollection"); } + + [Fact] + public async Task Get_ChildFlat_Returns_Vary_Header() + { + // Arrange + var requestMessage = + HttpRequestMessageBuilder.GetPrivateRequest(HttpMethod.Get, + $"1/collections/{RootCollection.Id}?page=1&pageSize=1&orderByDescending=notValid"); + + // Act + var response = await httpClient.AsCustomer(1).SendAsync(requestMessage); + + // Assert + response.StatusCode.Should().Be(HttpStatusCode.OK); + response.Headers.Vary.Should().HaveCount(2); + } } \ No newline at end of file diff --git a/src/IIIFPresentation/API/Features/Storage/StorageController.cs b/src/IIIFPresentation/API/Features/Storage/StorageController.cs index e40530c..a87e0d5 100644 --- a/src/IIIFPresentation/API/Features/Storage/StorageController.cs +++ b/src/IIIFPresentation/API/Features/Storage/StorageController.cs @@ -5,13 +5,14 @@ using API.Features.Storage.Validators; using API.Helpers; using API.Infrastructure; +using API.Infrastructure.Filters; using API.Infrastructure.Helpers; using API.Settings; +using IIIF.Presentation; +using IIIF.Serialisation; using MediatR; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; -using IIIF.Presentation; -using IIIF.Serialisation; using Models.API.Collection.Upsert; namespace API.Features.Storage; @@ -23,6 +24,7 @@ public class StorageController(IOptions options, IMediator mediator { [HttpGet("{*slug}")] [ETagCaching()] + [VaryHeader] public async Task GetHierarchicalCollection(int customerId, string slug = "") { var storageRoot = await Mediator.Send(new GetHierarchicalCollection(customerId, slug)); @@ -40,6 +42,7 @@ public async Task GetHierarchicalCollection(int customerId, strin [HttpGet("collections/{id}")] [ETagCaching] + [VaryHeader] public async Task Get(int customerId, string id, int? page = 1, int? pageSize = -1, string? orderBy = null, string? orderByDescending = null) { @@ -113,8 +116,8 @@ public async Task Delete(int customerId, string id) return await HandleDelete(new DeleteCollection(customerId, id)); } - - private IActionResult SeeOther(string location) + + private StatusCodeResult SeeOther(string location) { Response.Headers.Location = location; diff --git a/src/IIIFPresentation/API/Infrastructure/Filters/VaryHeaderAttribute.cs b/src/IIIFPresentation/API/Infrastructure/Filters/VaryHeaderAttribute.cs new file mode 100644 index 0000000..ecf4084 --- /dev/null +++ b/src/IIIFPresentation/API/Infrastructure/Filters/VaryHeaderAttribute.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Net.Http.Headers; + +namespace API.Infrastructure.Filters; + +public class VaryHeaderAttribute : ActionFilterAttribute +{ + private static readonly string[] VaryHeaders = ["X-IIIF-CS-Show-Extras", "Authorization"]; + + public override void OnActionExecuted(ActionExecutedContext context) + { + if (context.Result is not null) + context.HttpContext.Response.Headers.Append(HeaderNames.Vary, VaryHeaders); + } +} \ No newline at end of file