mirror of
https://github.com/AndrioCelos/TableturfBattleApp.git
synced 2026-03-22 01:44:12 -05:00
82 lines
3.8 KiB
C#
82 lines
3.8 KiB
C#
using System.Diagnostics.CodeAnalysis;
|
|
using System.Globalization;
|
|
using System.Net;
|
|
using System.Text;
|
|
using System.Web;
|
|
using Newtonsoft.Json;
|
|
using HttpListenerRequest = WebSocketSharp.Net.HttpListenerRequest;
|
|
using HttpListenerResponse = WebSocketSharp.Net.HttpListenerResponse;
|
|
|
|
namespace TableturfBattleServer;
|
|
internal static class HttpRequestHelper {
|
|
internal static readonly char[] DELIMITERS = [',', ' '];
|
|
internal const int CUSTOM_CARD_START = -10000;
|
|
internal const int RECEIVED_CUSTOM_CARD_START = -20000;
|
|
|
|
internal static void SetErrorResponse(this HttpListenerResponse response, Error error) {
|
|
var bytes = Encoding.UTF8.GetBytes(JsonUtils.Serialise(error));
|
|
SetResponse(response, error.HttpStatusCode, "application/json", bytes);
|
|
}
|
|
internal static void SetResponse(this HttpListenerResponse response, HttpStatusCode statusCode, string contentType, string content) {
|
|
var bytes = Encoding.UTF8.GetBytes(content);
|
|
SetResponse(response, statusCode, contentType, bytes);
|
|
}
|
|
internal static void SetResponse(this HttpListenerResponse response, HttpStatusCode statusCode, string contentType, byte[] content) {
|
|
response.StatusCode = (int) statusCode;
|
|
response.ContentType = contentType;
|
|
response.ContentLength64 = content.Length;
|
|
response.Close(content, true);
|
|
}
|
|
|
|
internal static Dictionary<string, string> DecodeFormData(Stream stream) => DecodeFormData(new StreamReader(stream).ReadToEnd());
|
|
internal static Dictionary<string, string> DecodeFormData(TextReader reader) => DecodeFormData(reader.ReadToEnd());
|
|
internal static Dictionary<string, string> DecodeFormData(string s) {
|
|
if (s.StartsWith('?')) s = s[1..];
|
|
return s != ""
|
|
? s.Split(['&']).Select(s => s.Split('=')).Select(a => a.Length == 2 ? a : throw new ArgumentException("Invalid form data"))
|
|
.ToDictionary(a => HttpUtility.UrlDecode(a[0]), a => HttpUtility.UrlDecode(a[1]))
|
|
: [];
|
|
}
|
|
|
|
internal static void SetStaticResponse(HttpListenerRequest request, HttpListenerResponse response, string jsonContent, string eTag, DateTime lastModified) {
|
|
if (request.HttpMethod is not ("GET" or "HEAD")) {
|
|
response.AddHeader("Allow", "GET, HEAD");
|
|
SetErrorResponse(response, new(HttpStatusCode.MethodNotAllowed, "MethodNotAllowed", "Invalid request method for this endpoint."));
|
|
return;
|
|
}
|
|
response.AppendHeader("Cache-Control", "max-age=86400");
|
|
response.AppendHeader("ETag", eTag);
|
|
response.AppendHeader("Last-Modified", 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, 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, HttpStatusCode.OK, "application/json", jsonContent);
|
|
}
|
|
}
|
|
|
|
internal static bool TryParseStageSelectionRule(string json, int maxPlayers, [MaybeNullWhen(false)] out StageSelectionRules stageSelectionRule) {
|
|
try {
|
|
stageSelectionRule = JsonUtils.Deserialise<StageSelectionRules>(json);
|
|
if (stageSelectionRule == null) return false;
|
|
stageSelectionRule.AddUnavailableStages(maxPlayers);
|
|
// Check that at least one stage is allowed.
|
|
for (var i = 0; i < StageDatabase.Stages.Count; i++) {
|
|
if (!stageSelectionRule.BannedStages.Contains(i)) return true;
|
|
}
|
|
return false;
|
|
} catch (JsonSerializationException) {
|
|
stageSelectionRule = null;
|
|
return false;
|
|
}
|
|
}
|
|
}
|