.NET WinForms-Anwendung (Core, Modules/CongressTrading, UI). Enthaelt .gitignore und settings.example.json als Konfigurationsvorlage. Echte settings.json mit Zugangsdaten ist bewusst ausgeschlossen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
82 lines
2.7 KiB
C#
82 lines
2.7 KiB
C#
using System.Net;
|
||
using System.Text;
|
||
using IBKRTrader.Core.Database;
|
||
using IBKRTrader.Core.Logging;
|
||
using IBKRTrader.Core.Settings;
|
||
|
||
namespace IBKRTrader.Core.Workers.BuiltIn;
|
||
|
||
/// <summary>
|
||
/// WebserverService – permanenter Service auf Basis von System.Net.HttpListener.
|
||
/// Lauscht auf http://localhost:{port}/ und liefert einen Status-JSON.
|
||
/// Wird später durch vollständige Web-UI erweitert.
|
||
/// </summary>
|
||
public class WebserverService : WorkerBase
|
||
{
|
||
private readonly SettingsService _settings;
|
||
private HttpListener? _listener;
|
||
|
||
public override string Name => "WebserverService";
|
||
public override string Module => "Core";
|
||
public override WorkerType Type => WorkerType.Service;
|
||
|
||
protected override TimeSpan? Interval => null; // Service = permanent
|
||
|
||
public WebserverService(LoggingService logger, DatabaseService db, SettingsService settings)
|
||
: base(logger, db)
|
||
{
|
||
_settings = settings;
|
||
Info.Active = settings.Settings.Webserver.Enabled;
|
||
Info.RunEvery = "Service";
|
||
}
|
||
|
||
protected override async Task ExecuteAsync(CancellationToken ct)
|
||
{
|
||
var port = _settings.Settings.Webserver.Port;
|
||
_listener = new HttpListener();
|
||
_listener.Prefixes.Add($"http://localhost:{port}/");
|
||
|
||
try
|
||
{
|
||
_listener.Start();
|
||
Logger.Info(Module, $"Webserver gestartet auf http://localhost:{port}/");
|
||
Info.Info = $"http://localhost:{port}/";
|
||
|
||
while (!ct.IsCancellationRequested)
|
||
{
|
||
// GetContextAsync blockiert – abbrechen via ct
|
||
var contextTask = _listener.GetContextAsync();
|
||
var cancelTask = Task.Delay(Timeout.Infinite, ct);
|
||
|
||
var completed = await Task.WhenAny(contextTask, cancelTask);
|
||
if (completed == cancelTask) break;
|
||
|
||
var ctx = await contextTask;
|
||
_ = HandleRequestAsync(ctx); // fire-and-forget pro Request
|
||
}
|
||
}
|
||
finally
|
||
{
|
||
_listener.Stop();
|
||
Logger.Info(Module, "Webserver gestoppt.");
|
||
}
|
||
}
|
||
|
||
private async Task HandleRequestAsync(HttpListenerContext ctx)
|
||
{
|
||
try
|
||
{
|
||
const string json = """{"status":"ok","app":"IBKRTrader","version":"1.0.0"}""";
|
||
var bytes = Encoding.UTF8.GetBytes(json);
|
||
|
||
ctx.Response.ContentType = "application/json";
|
||
ctx.Response.ContentLength64 = bytes.Length;
|
||
ctx.Response.StatusCode = 200;
|
||
|
||
await ctx.Response.OutputStream.WriteAsync(bytes);
|
||
ctx.Response.Close();
|
||
}
|
||
catch { /* Client hat getrennt */ }
|
||
}
|
||
}
|