From 407e0ced1b75d1230b5241f6ed3f955cc09174ae Mon Sep 17 00:00:00 2001 From: asleepyskye Date: Sun, 20 Jul 2025 18:40:16 -0400 Subject: [PATCH] fix(bot): add read func to handle requests w/ closed connections --- PluralKit.Bot/Services/HttpListenerService.cs | 40 ++++++++++++++++++- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/PluralKit.Bot/Services/HttpListenerService.cs b/PluralKit.Bot/Services/HttpListenerService.cs index d2bfc4ce..bafeae41 100644 --- a/PluralKit.Bot/Services/HttpListenerService.cs +++ b/PluralKit.Bot/Services/HttpListenerService.cs @@ -1,3 +1,4 @@ +using System.Text; using System.Text.Json; using Serilog; @@ -57,7 +58,7 @@ public class HttpListenerService private async Task RuntimeConfigSet(HttpContextBase ctx) { var key = ctx.Request.Url.Parameters["key"]; - var value = ctx.Request.DataAsString; + var value = ReadStream(ctx.Request.Data, ctx.Request.ContentLength); await _runtimeConfig.Set(key, value); await RuntimeConfigGet(ctx); } @@ -76,7 +77,7 @@ public class HttpListenerService var shardIdString = ctx.Request.Url.Parameters["shard_id"]; if (!int.TryParse(shardIdString, out var shardId)) return; - var packet = JsonSerializer.Deserialize(ctx.Request.DataAsString, _jsonSerializerOptions); + var packet = JsonSerializer.Deserialize(ReadStream(ctx.Request.Data, ctx.Request.ContentLength), _jsonSerializerOptions); var evt = DeserializeEvent(shardId, packet.EventType!, (JsonElement)packet.Payload!); if (evt != null) { @@ -107,4 +108,39 @@ public class HttpListenerService return null; } } + + //temporary re-implementation of the ReadStream function found in WatsonWebserver.Lite, but with handling for closed connections + //https://github.com/dotnet/WatsonWebserver/issues/171 + private static string ReadStream(Stream input, long contentLength) + { + if (input == null) throw new ArgumentNullException(nameof(input)); + if (!input.CanRead) throw new InvalidOperationException("Input stream is not readable"); + if (contentLength < 1) return ""; + + byte[] buffer = new byte[65536]; + long bytesRemaining = contentLength; + + using (MemoryStream ms = new MemoryStream()) + { + int read; + + while (bytesRemaining > 0) + { + read = input.Read(buffer, 0, buffer.Length); + if (read > 0) + { + ms.Write(buffer, 0, read); + bytesRemaining -= read; + } + else + { + throw new IOException("Connection closed before reading end of stream."); + } + } + + if (ms.Length < 1) return null; + var str = Encoding.Default.GetString(ms.ToArray()); + return str; + } + } } \ No newline at end of file