Files
MoShiro/backend/src/MoShiro.Backend/BackendHost.cs
T
justme 83e5120377 refactor!: rename the project from Monitor to MoShiro
Namespaces, assemblies, projects and directories, the solution, binaries,
images, systemd units, config paths, environment variables, protocol method
names, the media type and the raw chunk magic all move to MoShiro/moshiro.
Existing data and deployments are not compatible and must be recreated.
Also fix the architecture tests after the solution layout change and make
the update tests independent of their order.
2026-10-07 01:49:04 +08:00

66 lines
2.7 KiB
C#

using Fleet.Server;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using MoShiro.Backend.Api;
using MoShiro.Backend.Application;
using MoShiro.Backend.Gateway;
using MoShiro.Backend.Storage.Sqlite;
namespace MoShiro.Backend;
/// <summary>
/// 组合根:在这里显式注册所有层。配置来自 <c>appsettings.json</c>、环境变量(<c>MoShiro__DataDirectory</c> 等)和命令行。
/// 测试用 <see cref="Build"/> 在真实端口上启动整个后端。
/// </summary>
public static class BackendHost
{
public const string ConfigurationSection = "MoShiro";
public const int MaxRequestBodyBytes = 64 * 1024;
public static WebApplication Build(string[] args, Action<BackendOptions>? configureOptions = null, TimeProvider? time = null)
{
WebApplicationBuilder builder = WebApplication.CreateSlimBuilder(args);
var options = new BackendOptions();
builder.Configuration.GetSection(ConfigurationSection).Bind(options);
configureOptions?.Invoke(options);
builder.WebHost.ConfigureKestrel(kestrel => kestrel.Limits.MaxRequestBodySize = MaxRequestBodyBytes);
builder.Logging.AddSimpleConsole(console =>
{
console.SingleLine = true;
console.UseUtcTimestamp = true;
console.TimestampFormat = "yyyy-MM-ddTHH:mm:ss.fffZ ";
});
IServiceCollection services = builder.Services;
services.AddSingleton(time ?? TimeProvider.System);
services.AddMoShiroSqlite(options.DataDirectory);
// 国家和运营商:Backend 用节点的来源地址查一次(Probe、Agent 不访问任何外部服务);地址留空就不查
if (string.IsNullOrWhiteSpace(options.GeoLookupUrl))
{
services.AddSingleton<IGeoLookup, NoGeoLookup>();
}
else
{
services.AddSingleton<IGeoLookup>(new HttpGeoLookup(options.GeoLookupUrl));
}
services.AddMoShiroApplication(options);
services.AddMoShiroGateway();
services.AddMoShiroApi();
WebApplication app = builder.Build();
// 静默死亡的 Agent(断电、断网)不会关闭连接:15 秒一个 Ping,20 秒没有 Pong 就关闭,这样面板上的在线状态才可信
app.UseWebSockets(new WebSocketOptions { KeepAliveInterval = TimeSpan.FromSeconds(15), KeepAliveTimeout = TimeSpan.FromSeconds(20) });
app.UseMoShiroCors(options.CorsOrigins);
app.UseMoShiroApi();
app.MapMoShiroApi();
app.MapFleetEnrollment("/api/agent/v1/enroll");
app.MapFleetLink("/api/agent/v1/rpc");
return app;
}
}