config(battle-node): require NodeServerUrl from appsettings, no fallback

Move the localhost default off BattleNodeOptions and out of Program.cs
into an appsettings.json "BattleNode" section, and make AddBattleNode
throw at startup if the value is missing or blank. Deployments now must
set the URL explicitly, and dev keeps working via the checked-in value.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-07-04 15:10:23 -04:00
parent 6b0b467f31
commit 1bdcd8397b
4 changed files with 43 additions and 13 deletions

View File

@@ -18,15 +18,26 @@ public static class BattleNodeExtensions
/// instance the WebSocket handler constructs on connect.
/// </summary>
/// <param name="configure">
/// Optional callback to override <see cref="BattleNodeOptions"/> defaults. The default
/// <c>NodeServerUrl</c> assumes the EmulatedEntrypoint host on
/// <c>http://localhost:5148</c> and shares the port for the Socket.IO endpoint. Override
/// when the node runs on a different port/host or behind a reverse proxy.
/// Callback to populate <see cref="BattleNodeOptions"/>. Must set
/// <see cref="BattleNodeOptions.NodeServerUrl"/> — there is no hardcoded fallback; the
/// value is a deployment concern (localhost during dev, a real host[:port]/socket.io/
/// when the node runs behind a reverse proxy or on a separate box). Startup throws
/// <see cref="InvalidOperationException"/> if it's still empty after the callback runs.
/// </param>
/// <exception cref="InvalidOperationException">
/// <see cref="BattleNodeOptions.NodeServerUrl"/> is null, empty, or whitespace after
/// <paramref name="configure"/> runs.
/// </exception>
public static IServiceCollection AddBattleNode(this IServiceCollection services, Action<BattleNodeOptions>? configure = null)
{
var options = new BattleNodeOptions();
configure?.Invoke(options);
if (string.IsNullOrWhiteSpace(options.NodeServerUrl))
{
throw new InvalidOperationException(
"BattleNode:NodeServerUrl is not configured. Set it in appsettings.json under " +
"the \"BattleNode\" section (format: \"host[:port]/socket.io/\", no scheme prefix).");
}
services.AddSingleton(options);
services.AddSingleton<IBattleSessionStore, InMemoryBattleSessionStore>();
services.AddSingleton<IMatchingBridge, MatchingBridge>();