diff --git a/Examples/BookingSystem.AspNetCore/Helpers/ResponseContentHelper.cs b/Examples/BookingSystem.AspNetCore/Helpers/ResponseContentHelper.cs index 997975ac..cab8abd6 100644 --- a/Examples/BookingSystem.AspNetCore/Helpers/ResponseContentHelper.cs +++ b/Examples/BookingSystem.AspNetCore/Helpers/ResponseContentHelper.cs @@ -1,46 +1,15 @@ -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; - -namespace BookingSystem.AspNetCore.Helpers +namespace BookingSystem.AspNetCore.Helpers { public static class ResponseContentHelper { public static Microsoft.AspNetCore.Mvc.ContentResult GetContentResult(this OpenActive.Server.NET.OpenBookingHelper.ResponseContent response) { - return new CacheableContentResult + return new Microsoft.AspNetCore.Mvc.ContentResult { StatusCode = (int)response.StatusCode, Content = response.Content, - ContentType = response.ContentType, - CacheControlMaxAge = response.CacheControlMaxAge, + ContentType = response.ContentType }; } } - - /// - /// ContentResult that also sets Cache-Control: public, max-age=X, s-maxage=X - /// See https://developer.openactive.io/publishing-data/data-feeds/scaling-feeds for more information - /// - public class CacheableContentResult : Microsoft.AspNetCore.Mvc.ContentResult - { - public TimeSpan CacheControlMaxAge { get; set; } - - public override async Task ExecuteResultAsync(ActionContext context) - { - if (CacheControlMaxAge != null) - { - context.HttpContext.Response.GetTypedHeaders().CacheControl = - new Microsoft.Net.Http.Headers.CacheControlHeaderValue() - { - Public = true, - MaxAge = CacheControlMaxAge, - SharedMaxAge = CacheControlMaxAge, - }; - } - - await base.ExecuteResultAsync(context); - } - } } diff --git a/Examples/BookingSystem.AspNetFramework/Helpers/ResponseContentHelper.cs b/Examples/BookingSystem.AspNetFramework/Helpers/ResponseContentHelper.cs index b4eb3484..80b626b7 100644 --- a/Examples/BookingSystem.AspNetFramework/Helpers/ResponseContentHelper.cs +++ b/Examples/BookingSystem.AspNetFramework/Helpers/ResponseContentHelper.cs @@ -14,17 +14,6 @@ public static HttpResponseMessage GetContentResult(this OpenActive.Server.NET.Op StatusCode = response.StatusCode }; resp.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(response.ContentType); - /// Sets additional header Cache-Control: public, max-age=X, s-maxage=X - /// See https://developer.openactive.io/publishing-data/data-feeds/scaling-feeds for more information - if (response.CacheControlMaxAge != null) - { - resp.Headers.CacheControl = new CacheControlHeaderValue() - { - Public = true, - MaxAge = response.CacheControlMaxAge, - SharedMaxAge = response.CacheControlMaxAge - }; - } // Ensure custom error messages do not override responses HttpContext.Current.Response.TrySkipIisCustomErrors = true; return resp; diff --git a/OpenActive.Server.NET/CustomBookingEngine/CustomBookingEngine.cs b/OpenActive.Server.NET/CustomBookingEngine/CustomBookingEngine.cs index bdd16ee1..80f6f211 100644 --- a/OpenActive.Server.NET/CustomBookingEngine/CustomBookingEngine.cs +++ b/OpenActive.Server.NET/CustomBookingEngine/CustomBookingEngine.cs @@ -169,15 +169,16 @@ public async Task RenderDatasetSite() /// public async Task GetOpenDataRPDEPageForFeed(string feedname, string afterTimestamp, string afterId, string afterChangeNumber) { - return GetResponseContentFromRPDEPage( + return ResponseContent.RpdeResponse( (await RouteOpenDataRPDEPageForFeed( feedname, RpdeOrderingStrategyRouter.ConvertStringToLongOrThrow(afterTimestamp, nameof(afterTimestamp)), afterId, RpdeOrderingStrategyRouter.ConvertStringToLongOrThrow(afterChangeNumber, nameof(afterChangeNumber)) - ))); + )).ToString()); } + /// /// Handler for an RPDE endpoint /// Designed to be used on a single controller method with a "feedname" parameter, @@ -190,14 +191,11 @@ public async Task GetOpenDataRPDEPageForFeed(string feedname, s /// public async Task GetOpenDataRPDEPageForFeed(string feedname, long? afterTimestamp, string afterId, long? afterChangeNumber) { - return GetResponseContentFromRPDEPage(await RouteOpenDataRPDEPageForFeed(feedname, afterTimestamp, afterId, afterChangeNumber)); + return ResponseContent.RpdeResponse((await RouteOpenDataRPDEPageForFeed(feedname, afterTimestamp, afterId, afterChangeNumber)).ToString()); } - private ResponseContent GetResponseContentFromRPDEPage(RpdePage rpdePage) - { - var cacheMaxAge = rpdePage.Items.Count == 0 ? this.settings.RPDELastPageCacheDuration : this.settings.RPDEPageCacheDuration; - return ResponseContent.RpdeResponse(rpdePage.ToString(), cacheMaxAge); - } + + /// /// Handler for an RPDE endpoint diff --git a/OpenActive.Server.NET/OpenBookingHelper/Async/TastEx.cs b/OpenActive.Server.NET/OpenBookingHelper/Async/TastEx.cs deleted file mode 100644 index 7e33b59c..00000000 --- a/OpenActive.Server.NET/OpenBookingHelper/Async/TastEx.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; - -namespace OpenActive.Server.NET.OpenBookingHelper -{ - // https://www.meziantou.net/get-the-result-of-multiple-tasks-in-a-valuetuple-and-whenall.htm - public static partial class TaskEx - { - public static async Task<(T0, T1)> WhenAll(Task task0, Task task1) - { - if (task0 is null) - throw new ArgumentNullException(nameof(task0)); - if (task1 is null) - throw new ArgumentNullException(nameof(task1)); - - await Task.WhenAll(task0, task1).ConfigureAwait(false); - return (task0.Result, task1.Result); - } - - public static async Task<(T0, T1, T2)> WhenAll(Task task0, Task task1, Task task2) - { - if (task0 is null) - throw new ArgumentNullException(nameof(task0)); - if (task1 is null) - throw new ArgumentNullException(nameof(task1)); - if (task2 is null) - throw new ArgumentNullException(nameof(task2)); - - await Task.WhenAll(task0, task1, task2).ConfigureAwait(false); - return (task0.Result, task1.Result, task2.Result); - } - - public static async Task<(T0, T1, T2, T3)> WhenAll(Task task0, Task task1, Task task2, Task task3) - { - if (task0 is null) - throw new ArgumentNullException(nameof(task0)); - if (task1 is null) - throw new ArgumentNullException(nameof(task1)); - if (task2 is null) - throw new ArgumentNullException(nameof(task2)); - if (task3 is null) - throw new ArgumentNullException(nameof(task3)); - - await Task.WhenAll(task0, task1, task2, task3).ConfigureAwait(false); - return (task0.Result, task1.Result, task2.Result, task3.Result); - } - - public static async Task<(T0, T1, T2, T3, T4)> WhenAll(Task task0, Task task1, Task task2, Task task3, Task task4) - { - if (task0 is null) - throw new ArgumentNullException(nameof(task0)); - if (task1 is null) - throw new ArgumentNullException(nameof(task1)); - if (task2 is null) - throw new ArgumentNullException(nameof(task2)); - if (task3 is null) - throw new ArgumentNullException(nameof(task3)); - if (task4 is null) - throw new ArgumentNullException(nameof(task4)); - - await Task.WhenAll(task0, task1, task2, task3, task4).ConfigureAwait(false); - return (task0.Result, task1.Result, task2.Result, task3.Result, task4.Result); - } - - public static async Task<(T0, T1, T2, T3, T4, T5)> WhenAll(Task task0, Task task1, Task task2, Task task3, Task task4, Task task5) - { - if (task0 is null) - throw new ArgumentNullException(nameof(task0)); - if (task1 is null) - throw new ArgumentNullException(nameof(task1)); - if (task2 is null) - throw new ArgumentNullException(nameof(task2)); - if (task3 is null) - throw new ArgumentNullException(nameof(task3)); - if (task4 is null) - throw new ArgumentNullException(nameof(task4)); - if (task5 is null) - throw new ArgumentNullException(nameof(task5)); - - await Task.WhenAll(task0, task1, task2, task3, task4, task5).ConfigureAwait(false); - return (task0.Result, task1.Result, task2.Result, task3.Result, task4.Result, task5.Result); - } - - public static async Task<(T0, T1, T2, T3, T4, T5, T6)> WhenAll(Task task0, Task task1, Task task2, Task task3, Task task4, Task task5, Task task6) - { - if (task0 is null) - throw new ArgumentNullException(nameof(task0)); - if (task1 is null) - throw new ArgumentNullException(nameof(task1)); - if (task2 is null) - throw new ArgumentNullException(nameof(task2)); - if (task3 is null) - throw new ArgumentNullException(nameof(task3)); - if (task4 is null) - throw new ArgumentNullException(nameof(task4)); - if (task5 is null) - throw new ArgumentNullException(nameof(task5)); - if (task6 is null) - throw new ArgumentNullException(nameof(task6)); - - await Task.WhenAll(task0, task1, task2, task3, task4, task5, task6).ConfigureAwait(false); - return (task0.Result, task1.Result, task2.Result, task3.Result, task4.Result, task5.Result, task6.Result); - } - - public static TaskAwaiter<(T1, T2)> GetAwaiter(this ValueTuple, Task> tasks) - { - return WhenAll(tasks.Item1, tasks.Item2).GetAwaiter(); - } - - public static TaskAwaiter<(T1, T2, T3)> GetAwaiter(this ValueTuple, Task, Task> tasks) - { - return WhenAll(tasks.Item1, tasks.Item2, tasks.Item3).GetAwaiter(); - } - - public static TaskAwaiter<(T1, T2, T3, T4)> GetAwaiter(this ValueTuple, Task, Task, Task> tasks) - { - return WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4).GetAwaiter(); - } - - public static TaskAwaiter<(T1, T2, T3, T4, T5)> GetAwaiter(this ValueTuple, Task, Task, Task, Task> tasks) - { - return WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4, tasks.Item5).GetAwaiter(); - } - - public static TaskAwaiter<(T1, T2, T3, T4, T5, T6)> GetAwaiter(this ValueTuple, Task, Task, Task, Task, Task> tasks) - { - return WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4, tasks.Item5, tasks.Item6).GetAwaiter(); - } - - public static TaskAwaiter<(T1, T2, T3, T4, T5, T6, T7)> GetAwaiter(this ValueTuple, Task, Task, Task, Task, Task, Task> tasks) - { - return WhenAll(tasks.Item1, tasks.Item2, tasks.Item3, tasks.Item4, tasks.Item5, tasks.Item6, tasks.Item7).GetAwaiter(); - } - } -} \ No newline at end of file diff --git a/OpenActive.Server.NET/OpenBookingHelper/Content/ResponseContent.cs b/OpenActive.Server.NET/OpenBookingHelper/Content/ResponseContent.cs index 2dd5a3c6..7a372724 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Content/ResponseContent.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Content/ResponseContent.cs @@ -1,5 +1,4 @@ using OpenActive.NET; -using System; using System.Net; namespace OpenActive.Server.NET.OpenBookingHelper @@ -61,14 +60,13 @@ public static ResponseContent OrdersFeedRpdeResponse(string content) }; } - public static ResponseContent RpdeResponse(string content, TimeSpan cacheControlMaxAge) + public static ResponseContent RpdeResponse(string content) { return new ResponseContent { Content = content, ContentType = OpenActiveMediaTypes.RealtimePagedDataExchange.Version1, - StatusCode = HttpStatusCode.OK, - CacheControlMaxAge = cacheControlMaxAge + StatusCode = HttpStatusCode.OK }; } @@ -84,10 +82,6 @@ public static ResponseContent RpdeResponse(string content, TimeSpan cacheControl // Summary: // The intended HTTP status code of the response public HttpStatusCode StatusCode { get; internal set; } = HttpStatusCode.OK; - // - // Summary: - // The Cache-Control header intended for the response (public, max-age=X) - public TimeSpan CacheControlMaxAge { get; internal set; } public override string ToString() { diff --git a/OpenActive.Server.NET/OpenBookingHelper/Settings/BookingEngineSettings.cs b/OpenActive.Server.NET/OpenBookingHelper/Settings/BookingEngineSettings.cs index 4e2ce37a..551b2c54 100644 --- a/OpenActive.Server.NET/OpenBookingHelper/Settings/BookingEngineSettings.cs +++ b/OpenActive.Server.NET/OpenBookingHelper/Settings/BookingEngineSettings.cs @@ -26,16 +26,6 @@ public class BookingEngineSettings public OrdersRPDEFeedGenerator OrdersFeedGenerator { get; set; } public OrdersRPDEFeedGenerator OrderProposalsFeedGenerator { get; set; } public SellerStore SellerStore { get; set; } - public bool HasSingleSeller { get; set; } = false; - /// - /// TTL in the Cache-Control header for all RPDE pages that contain greater than zero items - /// See https://developer.openactive.io/publishing-data/data-feeds/scaling-feeds for CDN configuration instructions - /// - public TimeSpan RPDEPageCacheDuration { get; set; } = TimeSpan.FromHours(1); - /// - /// TTL in the Cache-Control header for all RPDE pages that contain zero items - /// See https://developer.openactive.io/publishing-data/data-feeds/scaling-feeds for CDN configuration instructions - /// - public TimeSpan RPDELastPageCacheDuration { get; set; } = TimeSpan.FromSeconds(8); + public bool HasSingleSeller { get; set; } } }