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