Implement engine-bridge v2 plugin masquerade (#10)

This commit is contained in:
minsung
2026-04-07 16:08:31 +09:00
parent 4cee3c2d86
commit b1c2383a54
18 changed files with 1017 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace Recordingtest.EngineBridge.IntegrationTests;
public sealed class FakeBridgeServer : IDisposable
{
public Dictionary<string, string> Responses { get; } = new();
public TimeSpan ResponseDelay { get; set; } = TimeSpan.Zero;
private readonly HttpListener _listener;
private readonly Thread _thread;
private volatile bool _stop;
public int Port { get; }
public string BaseUrl => $"http://localhost:{Port}";
public FakeBridgeServer()
{
Port = FindFreePort();
_listener = new HttpListener();
_listener.Prefixes.Add($"http://localhost:{Port}/");
_listener.Start();
_thread = new Thread(Loop) { IsBackground = true };
_thread.Start();
}
private static int FindFreePort()
{
var l = new TcpListener(IPAddress.Loopback, 0);
l.Start();
var p = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();
return p;
}
private void Loop()
{
while (!_stop && _listener.IsListening)
{
HttpListenerContext ctx;
try { ctx = _listener.GetContext(); }
catch { return; }
try
{
if (ResponseDelay > TimeSpan.Zero) Thread.Sleep(ResponseDelay);
var path = ctx.Request.Url?.AbsolutePath ?? "/";
if (Responses.TryGetValue(path, out var body))
{
var bytes = Encoding.UTF8.GetBytes(body);
ctx.Response.StatusCode = 200;
ctx.Response.ContentType = "application/json";
ctx.Response.OutputStream.Write(bytes, 0, bytes.Length);
}
else
{
ctx.Response.StatusCode = 404;
}
ctx.Response.OutputStream.Close();
}
catch { try { ctx.Response.Abort(); } catch { } }
}
}
public void Dispose()
{
_stop = true;
try { _listener.Stop(); } catch { }
try { _listener.Close(); } catch { }
}
}