Server: Complete HTTP caching support

This commit is contained in:
Andrio Celos 2022-10-06 11:32:12 +11:00
parent 3b4e1a865f
commit a1e91f1e09
2 changed files with 31 additions and 13 deletions

View File

@ -1631,6 +1631,7 @@ public static class CardDatabase {
};
public static Version Version { get; } = new(1, 1, 0, 0);
public static DateTime LastModified { get; } = new(2022, 9, 2, 0, 0, 0, DateTimeKind.Utc);
public static string JSON { get; }
public static ReadOnlyCollection<Card> Cards { get; }

View File

@ -1,4 +1,5 @@
using System.Net;
using System.Globalization;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Timers;
@ -8,6 +9,8 @@ using Newtonsoft.Json;
using WebSocketSharp.Server;
using HttpListenerRequest = WebSocketSharp.Net.HttpListenerRequest;
using HttpListenerResponse = WebSocketSharp.Net.HttpListenerResponse;
using Timer = System.Timers.Timer;
namespace TableturfBattleServer;
@ -75,18 +78,7 @@ internal class Program {
}
}
} else if (e.Request.RawUrl == "/api/cards") {
if (e.Request.HttpMethod is not ("GET" or "HEAD")) {
e.Response.StatusCode = (int) HttpStatusCode.MethodNotAllowed;
e.Response.AddHeader("Allow", "GET, HEAD");
return;
}
e.Response.AppendHeader("Cache-Control", "max-age=86400");
e.Response.AppendHeader("ETag", CardDatabase.Version.ToString());
if (e.Response.Headers["If-None-Match"] == CardDatabase.Version.ToString()) {
e.Response.StatusCode = (int) HttpStatusCode.NotModified;
} else {
SetResponse(e.Response, (int) HttpStatusCode.OK, "application/json", CardDatabase.JSON);
}
SetStaticResponse(e.Request, e.Response, CardDatabase.JSON, CardDatabase.Version.ToString(), CardDatabase.LastModified);
} else {
var m = Regex.Match(e.Request.RawUrl, @"^/api/games/([\w-]+)(?:/(\w+)(?:/([\w-]+))?)?$", RegexOptions.Compiled);
if (m.Success) {
@ -372,4 +364,29 @@ internal class Program {
.ToDictionary(a => HttpUtility.UrlDecode(a[0]), a => HttpUtility.UrlDecode(a[1]))
: new();
}
private static void SetStaticResponse(HttpListenerRequest request, HttpListenerResponse response, string jsonContent, string eTag, DateTime lastModified) {
if (request.HttpMethod is not ("GET" or "HEAD")) {
response.StatusCode = (int) HttpStatusCode.MethodNotAllowed;
response.AddHeader("Allow", "GET, HEAD");
return;
}
response.AppendHeader("Cache-Control", "max-age=86400");
response.AppendHeader("ETag", eTag);
response.AppendHeader("Last-Modified", CardDatabase.LastModified.ToString("ddd, dd MMM yyyy HH:mm:ss \"GMT\""));
var ifNoneMatch = request.Headers["If-None-Match"];
if (ifNoneMatch != null) {
if (request.Headers["If-None-Match"] == eTag)
response.StatusCode = (int) HttpStatusCode.NotModified;
else
SetResponse(response, (int) HttpStatusCode.OK, "application/json", jsonContent);
} else {
if (DateTime.TryParseExact(request.Headers["If-Modified-Since"], "ddd, dd MMM yyyy HH:mm:ss \"GMT\"", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var dateTime)
&& dateTime >= lastModified.ToUniversalTime())
response.StatusCode = (int) HttpStatusCode.NotModified;
else
SetResponse(response, (int) HttpStatusCode.OK, "application/json", jsonContent);
}
}
}