Use QueryParser for redirect and expose method for new clients

This commit is contained in:
Infi
2024-08-28 12:42:01 +02:00
parent 2d7d1c9615
commit 7b96b52217
4 changed files with 23 additions and 23 deletions
+12 -1
View File
@@ -16,7 +16,7 @@ public class Processing
Plugin = plugin; Plugin = plugin;
} }
public string ReadChannelName(Chunk[] channelName) internal string ReadChannelName(Chunk[] channelName)
{ {
return string.Join("", channelName.Select(chunk => ProcessChunk(chunk, noColor: true))); return string.Join("", channelName.Select(chunk => ProcessChunk(chunk, noColor: true)));
} }
@@ -44,6 +44,17 @@ public class Processing
return response; return response;
} }
internal async Task PrepareNewClient(SSEConnection sse)
{
var messages = await WebserverUtil.FrameworkWrapper(ReadMessageList);
var channels = await Plugin.Framework.RunOnTick(Plugin.ChatLogWindow.GetAvailableChannels);
var channelName = await Plugin.Framework.RunOnTick(() => ReadChannelName(Plugin.ChatLogWindow.PreviousChannel));
sse.OutboundQueue.Enqueue(new NewMessageEvent(new Messages(messages)));
sse.OutboundQueue.Enqueue(new SwitchChannelEvent(new SwitchChannel(channelName)));
sse.OutboundQueue.Enqueue(new ChannelListEvent(new ChannelList(channels.ToDictionary(pair => pair.Key, pair => (uint)pair.Value))));
}
private string ProcessChunk(Chunk chunk, bool noColor = false) private string ProcessChunk(Chunk chunk, bool noColor = false)
{ {
if (chunk is IconChunk { } icon) if (chunk is IconChunk { } icon)
+8 -15
View File
@@ -125,14 +125,14 @@ public class RouteController
{ {
var currentTick = Environment.TickCount64; var currentTick = Environment.TickCount64;
if (RateLimit.TryGetValue(ctx.Request.Source.IpAddress, out var timestamp) && timestamp > currentTick) if (RateLimit.TryGetValue(ctx.Request.Source.IpAddress, out var timestamp) && timestamp > currentTick)
return await Redirect(ctx, "/", "message", "Rate limit active."); return await Redirect(ctx, "/", ("message", "Rate limit active."), ("retry", "12345"));
// The next request will be rate limited for 10s // The next request will be rate limited for 10s
RateLimit[ctx.Request.Source.IpAddress] = currentTick + 10_000; RateLimit[ctx.Request.Source.IpAddress] = currentTick + 10_000;
var authcode = HttpUtility.ParseQueryString(ctx.Request.DataAsString ?? "").Get("authcode"); var authcode = HttpUtility.ParseQueryString(ctx.Request.DataAsString ?? "").Get("authcode");
if (authcode == null || authcode != Plugin.Config.WebinterfacePassword) if (authcode == null || authcode != Plugin.Config.WebinterfacePassword)
return await Redirect(ctx, "/", "message", "Authentication failed."); return await Redirect(ctx, "/", ("message", "Authentication failed."));
var token = WebinterfaceUtil.GenerateSimpleToken(); var token = WebinterfaceUtil.GenerateSimpleToken();
SessionTokens.TryAdd(token, true); SessionTokens.TryAdd(token, true);
@@ -208,16 +208,9 @@ public class RouteController
Plugin.Log.Information($"Client connected: {ctx.Guid}"); Plugin.Log.Information($"Client connected: {ctx.Guid}");
var sse = new SSEConnection(Core.TokenSource.Token); var sse = new SSEConnection(Core.TokenSource.Token);
await Core.Processing.PrepareNewClient(sse);
Core.EventConnections.Add(sse); Core.EventConnections.Add(sse);
// TODO Check if reconnect or new connection
var messages = await WebserverUtil.FrameworkWrapper(Core.Processing.ReadMessageList);
var channels = await Plugin.Framework.RunOnTick(Plugin.ChatLogWindow.GetAvailableChannels);
var channelName = await Plugin.Framework.RunOnTick(() => Core.Processing.ReadChannelName(Plugin.ChatLogWindow.PreviousChannel));
sse.OutboundQueue.Enqueue(new NewMessageEvent(new Messages(messages)));
sse.OutboundQueue.Enqueue(new SwitchChannelEvent(new SwitchChannel(channelName)));
sse.OutboundQueue.Enqueue(new ChannelListEvent(new ChannelList(channels.ToDictionary(pair => pair.Key, pair => (uint)pair.Value))));
await sse.HandleEventLoop(ctx); await sse.HandleEventLoop(ctx);
// It should always be done after return // It should always be done after return
@@ -232,13 +225,13 @@ public class RouteController
#endregion #endregion
#region RedirectHelper #region RedirectHelper
public static async Task<bool> Redirect(HttpContextBase ctx, string location, params string[] parameter) public static async Task<bool> Redirect(HttpContextBase ctx, string location, params (string, string)[] parameter)
{ {
var query = "?"; var query = HttpUtility.ParseQueryString(string.Empty);
foreach (var (content, index) in parameter.WithIndex()) foreach (var (key, value) in parameter)
query += index % 2 == 0 ? $"{content}=" : Uri.EscapeDataString(content); query.Add(key, value);
ctx.Response.Headers.Add("Location", $"{location}{query}"); ctx.Response.Headers.Add("Location", $"{location}?{query}");
ctx.Response.StatusCode = 302; ctx.Response.StatusCode = 302;
return await ctx.Response.Send(); return await ctx.Response.Send();
} }
+1 -5
View File
@@ -1,12 +1,10 @@
using System.Text; using ChatTwo.Http.MessageProtocol;
using ChatTwo.Http.MessageProtocol;
using WatsonWebserver.Core; using WatsonWebserver.Core;
namespace ChatTwo.Http; namespace ChatTwo.Http;
public class SSEConnection public class SSEConnection
{ {
private long Index;
private bool Stopping; private bool Stopping;
private readonly CancellationToken Token; private readonly CancellationToken Token;
@@ -42,8 +40,6 @@ public class SSEConnection
Plugin.Log.Information($"Client disconnected: {ctx.Guid}"); Plugin.Log.Information($"Client disconnected: {ctx.Guid}");
return; return;
} }
Index++;
} }
} }
catch (TaskCanceledException) catch (TaskCanceledException)
+2 -2
View File
@@ -124,13 +124,13 @@ public class ServerCore : IAsyncDisposable
{ {
if (RouteController.SessionTokens.IsEmpty) if (RouteController.SessionTokens.IsEmpty)
{ {
await RouteController.Redirect(ctx, "/", "message", "Invalid session token."); await RouteController.Redirect(ctx, "/", ("message", "Invalid session token."));
return; return;
} }
var cookies = WebserverUtil.GetCookieData(ctx.Request.Headers.Get("Cookie") ?? ""); var cookies = WebserverUtil.GetCookieData(ctx.Request.Headers.Get("Cookie") ?? "");
if (!cookies.TryGetValue("ChatTwo-token", out var token) || !RouteController.SessionTokens.ContainsKey(token)) if (!cookies.TryGetValue("ChatTwo-token", out var token) || !RouteController.SessionTokens.ContainsKey(token))
await RouteController.Redirect(ctx, "/", "message", "Invalid session token."); await RouteController.Redirect(ctx, "/", ("message", "Invalid session token."));
// Do nothing to let auth pass // Do nothing to let auth pass
} }