Merge commit '0952958af7685646cdbf2a4907c6e2ae59d4d352'

This commit is contained in:
2026-05-28 10:44:03 +08:00
parent 4eeaa3fef3
commit 35bdb08d11
144 changed files with 33730 additions and 392 deletions

View File

@@ -1,13 +1,124 @@
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using Flyshot.ControllerClientCompat;
using Flyshot.Server.Host;
using Flyshot.Server.Host.Middleware;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using NLog.Web;
using Swashbuckle.AspNetCore.SwaggerGen;
app.MapGet("/", () => Results.Redirect("/healthz"));
app.MapGet("/healthz", () => Results.Ok(new
// NLog: 在 ASP.NET Core 启动前完成配置加载,确保最早期的日志也能被捕获。
NLog.LogManager.Setup().LoadConfigurationFromAppSettings();
var logger = NLog.LogManager.GetCurrentClassLogger();
try
{
status = "ok",
service = "flyshot-server-host"
}));
logger.Info("Flyshot Server Host 启动中...");
app.Run();
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.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 文档;调试页据此渲染端点标题。
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;