- 新增 Obfuscar 混淆发布脚本、发布测试与产物隐私检查 - 调整 VS Code 发布任务和宿主发布配置,统一走混淆流程 - 为 debug 页面内嵌静态接口说明,并补充对应集成测试 - 更新 README 与设计计划文档,记录跨平台发布约束
131 lines
4.7 KiB
C#
131 lines
4.7 KiB
C#
using Flyshot.ControllerClientCompat;
|
||
using Flyshot.Server.Host;
|
||
using Flyshot.Server.Host.Middleware;
|
||
using Flyshot.Server.Host.Services;
|
||
using Microsoft.Extensions.Options;
|
||
using Microsoft.OpenApi.Models;
|
||
using NLog.Web;
|
||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||
|
||
// NLog: 在 ASP.NET Core 启动前完成配置加载,确保最早期的日志也能被捕获。
|
||
NLog.LogManager.Setup().LoadConfigurationFromAppSettings();
|
||
var logger = NLog.LogManager.GetCurrentClassLogger();
|
||
|
||
try
|
||
{
|
||
logger.Info("Flyshot Server Host 启动中...");
|
||
|
||
var builder = WebApplication.CreateBuilder(args);
|
||
|
||
// NLog: 替换默认日志提供者为 NLog,清除其他 Provider 避免重复输出。
|
||
builder.Logging.ClearProviders();
|
||
builder.Host.UseNLog();
|
||
|
||
builder.Services.Configure<HostSwaggerOptions>(builder.Configuration.GetSection("Swagger"));
|
||
builder.Services.Configure<HostCorsOptions>(builder.Configuration.GetSection("Cors"));
|
||
builder.Services.AddControllerClientCompat(builder.Configuration);
|
||
|
||
// 注册服务启动时自动初始化机器人的托管服务;配置缺失时自动跳过。
|
||
builder.Services.AddHostedService<AutoInitRobotHostedService>();
|
||
|
||
builder.Services.AddControllers();
|
||
builder.Services.AddEndpointsApiExplorer();
|
||
|
||
var swaggerOptions = builder.Configuration.GetSection("Swagger").Get<HostSwaggerOptions>() ?? new HostSwaggerOptions();
|
||
builder.Services.AddSwaggerGen(options =>
|
||
{
|
||
options.SwaggerDoc(swaggerOptions.DocumentName, new OpenApiInfo
|
||
{
|
||
Title = swaggerOptions.Title,
|
||
Version = swaggerOptions.Version
|
||
});
|
||
|
||
// 把控制器与 DTO 上的 /// summary 注释纳入 OpenAPI 文档;当前主要服务 Swagger UI,
|
||
// 调试页的人类可读说明已经静态内嵌在 debug.html 中,不再依赖发布目录中的 XML 文档。
|
||
var xmlDocumentationPath = Path.Combine(AppContext.BaseDirectory, $"{typeof(Program).Assembly.GetName().Name}.xml");
|
||
if (File.Exists(xmlDocumentationPath))
|
||
{
|
||
options.IncludeXmlComments(xmlDocumentationPath, includeControllerXmlComments: true);
|
||
}
|
||
});
|
||
|
||
var corsOptions = builder.Configuration.GetSection("Cors").Get<HostCorsOptions>() ?? new HostCorsOptions();
|
||
builder.Services.AddCors(options =>
|
||
{
|
||
options.AddPolicy(corsOptions.PolicyName, policyBuilder =>
|
||
{
|
||
// 兼容本地调试时最常见的任意源配置,同时保留显式白名单模式。
|
||
if (corsOptions.AllowedOrigins.Length == 1 && string.Equals(corsOptions.AllowedOrigins[0], "*", StringComparison.Ordinal))
|
||
{
|
||
policyBuilder.AllowAnyOrigin();
|
||
}
|
||
else
|
||
{
|
||
policyBuilder.WithOrigins(corsOptions.AllowedOrigins);
|
||
}
|
||
|
||
if (corsOptions.AllowedMethods.Length == 1 && string.Equals(corsOptions.AllowedMethods[0], "*", StringComparison.Ordinal))
|
||
{
|
||
policyBuilder.AllowAnyMethod();
|
||
}
|
||
else
|
||
{
|
||
policyBuilder.WithMethods(corsOptions.AllowedMethods);
|
||
}
|
||
|
||
if (corsOptions.AllowedHeaders.Length == 1 && string.Equals(corsOptions.AllowedHeaders[0], "*", StringComparison.Ordinal))
|
||
{
|
||
policyBuilder.AllowAnyHeader();
|
||
}
|
||
else
|
||
{
|
||
policyBuilder.WithHeaders(corsOptions.AllowedHeaders);
|
||
}
|
||
});
|
||
});
|
||
|
||
var app = builder.Build();
|
||
|
||
var resolvedSwaggerOptions = app.Services.GetRequiredService<IOptions<HostSwaggerOptions>>().Value;
|
||
var resolvedCorsOptions = app.Services.GetRequiredService<IOptions<HostCorsOptions>>().Value;
|
||
|
||
if (resolvedSwaggerOptions.Enabled)
|
||
{
|
||
app.UseSwagger(options =>
|
||
{
|
||
options.RouteTemplate = resolvedSwaggerOptions.JsonRouteTemplate;
|
||
});
|
||
|
||
app.UseSwaggerUI(options =>
|
||
{
|
||
options.RoutePrefix = resolvedSwaggerOptions.RoutePrefix;
|
||
options.SwaggerEndpoint(
|
||
$"/swagger/{resolvedSwaggerOptions.DocumentName}/swagger.json",
|
||
$"{resolvedSwaggerOptions.Title} {resolvedSwaggerOptions.Version}");
|
||
options.DocumentTitle = resolvedSwaggerOptions.Title;
|
||
});
|
||
}
|
||
|
||
app.UseCors(resolvedCorsOptions.PolicyName);
|
||
app.UseStaticFiles();
|
||
|
||
// 注册 HTTP 请求/响应日志中间件,记录所有 API 调用的输入输出。
|
||
app.UseMiddleware<RequestResponseLoggingMiddleware>();
|
||
|
||
app.MapControllers();
|
||
|
||
logger.Info("Flyshot Server Host 已就绪,开始监听请求。");
|
||
app.Run();
|
||
}
|
||
catch (Exception exception)
|
||
{
|
||
logger.Error(exception, "Flyshot Server Host 启动失败。");
|
||
throw;
|
||
}
|
||
finally
|
||
{
|
||
NLog.LogManager.Shutdown();
|
||
}
|
||
|
||
public partial class Program;
|