track/src/TrackCenter.Api/TrackCenterApiModule.cs
xiaolipro 707e6131fa
All checks were successful
Build and Deploy / deploy (push) Successful in 55s
解耦合
2026-10-28 11:50:58 +08:00

197 lines
7.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Fake.AspNetCore;
using Fake.AspNetCore.Auditing;
using Fake.AspNetCore.Authentication;
using Fake.AspNetCore.ExceptionHandling;
using Fake.AspNetCore.Newtonsoft;
using Fake.AspNetCore.Swagger;
using Fake.Autofac;
using Fake.FeiShu;
using Fake.Json;
using Fake.Messaging.Dashboard;
using Fake.Modularity;
using Fake.Security.Claims;
using Fake.Serilog;
using FluentValidation.AspNetCore;
using Hangfire;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Mvc.Authorization;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;
using TrackCenter.Application;
using TrackCenter.Application.Hangfire;
using TrackCenter.Repository;
using TrackCenter.Repository.Otel;
using TrackCenter.Repository.Otel.Options;
using TrackCenter.Application.Filters;
namespace TrackCenter.Api;
[DependsOn(typeof(FakeAutofacModule))]
[DependsOn(typeof(FakeAspNetCoreModule))]
[DependsOn(typeof(TrackCenterApplicationModule))]
[DependsOn(typeof(TrackCenterRepositoryModule))]
[DependsOn(typeof(FakeMessagingDashboardModule))]
[DependsOn(typeof(FakeSerilogModule))]
public class TrackCenterApiModule : FakeModule
{
private const string DefaultCorsPolicyName = "default";
public override void PreConfigureServices(ServiceConfigurationContext context)
{
FakeClaimTypes.UserId = "mapId";
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var services = context.Services;
var configuration = context.Services.GetConfiguration();
services.Configure<FakeAspNetCoreMvcOptions>(options =>
{
options.ApplicationServices2Controller<TrackCenterApplicationModule>();
});
// 配置签名验证选项
services.Configure<SignatureValidationOptions>(configuration.GetSection("SignatureValidation"));
// 全局授权配置:所有接口默认需要授权
services.AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
// 添加签名验证过滤器
options.Filters.Add<SignatureValidationFilter>();
}).AddNewtonsoftJson();
//Json格式化全局处理
services.Configure<FakeJsonSerializerOptions>(options =>
{
options.InputDateTimeFormats.Add("yyyy-MM-dd HH:mm:ss");
options.LongToString = true;
});
context.Services.AddFakeNewtonsoft();
services.AddFakeSwaggerGen(addSecurity:true)
.AddFakeAspNetCoreAuditing()
.AddFeiShuNotification();
services.AddFluentValidationAutoValidation().AddFluentValidationClientsideAdapters();
var otelOptions = new OTelOptions()
{
EnableAspNetCore = true,
EnableHttpClient = true,
EnableSql = true
};
configuration.GetSection("OTel").Bind(otelOptions);
ActivityHelper.InitActivitySource(otelOptions);
services.AddOpenTelemetry()
.ConfigureResource(resource => resource.AddService(otelOptions.ServiceName))
.WithTracing(tracing =>
{
switch (otelOptions.SamplerType)
{
case SamplerType.AlwaysOn:
tracing.SetSampler(new AlwaysOnSampler());
break;
case SamplerType.AlwaysOff:
tracing.SetSampler(new AlwaysOffSampler());
break;
case SamplerType.ParentBasedSampler:
{
Sampler childSampler = otelOptions.ChildBasedSampler switch
{
SamplerType.AlwaysOn => new AlwaysOnSampler(),
SamplerType.AlwaysOff => new AlwaysOffSampler(),
SamplerType.TraceIdRatio =>
new TraceIdRatioBasedSampler(otelOptions.SamplerProbability),
_ => new AlwaysOnSampler(),
};
tracing.SetSampler(new ParentBasedSampler(childSampler));
}
break;
case SamplerType.TraceIdRatio:
tracing.SetSampler(new TraceIdRatioBasedSampler(otelOptions.SamplerProbability));
break;
default:
tracing.SetSampler(new AlwaysOnSampler());
break;
}
tracing.AddSource(otelOptions.ServiceName);
});
services.AddCors(options =>
{
options.AddPolicy(DefaultCorsPolicyName, builder =>
{
builder.WithOrigins(configuration.GetSection("App:CorsOrigins").Get<string[]>() ?? [])
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
services.AddFakeJwtAuthentication();
// 添加授权服务
services.AddAuthorization();
services.Configure<ForwardedHeadersOptions>(options =>
{
// 反向代理场景下恢复客户端真实来源信息,供 Swagger、鉴权和重定向等中间件使用
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor |
ForwardedHeaders.XForwardedProto |
ForwardedHeaders.XForwardedHost;
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
}
public override void ConfigureApplication(ApplicationConfigureContext context)
{
var app = context.GetWebApplication();
var configuration = context.GetConfiguration();
// 必须在读取 Scheme/Host/PathBase 的中间件之前执行,否则 Swagger 会生成错误的请求地址
app.UseForwardedHeaders();
app.Use(async (httpContext, next) =>
{
httpContext.Request.EnableBuffering();
await next.Invoke();
});
// 虚拟路由-网关适配
app.UsePathBase(app.Configuration["ASPNETCORE_PATHBASE"]);
app.UseFakeExceptionHandling();
app.MapControllers();
// Configure the HTTP request pipeline.
app.UseFakeSwagger();
app.UseRouting();
app.UseCors(DefaultCorsPolicyName);
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
DisplayStorageConnectionString = false,
IgnoreAntiforgeryToken = true,
// 「返回站点」链接;PathBase 已由 UsePathBase 处理,勿再设 PrefixPath,否则会变成 /track/track/hangfire/...
AppPath = configuration["ASPNETCORE_PATHBASE"],
DashboardTitle = "轨迹预警任务",
Authorization = [new AnonymousHangfireAuthorizationFilter()]
});
// 必须在 UsePathBase 之后:完整对外路径为 {PathBase}/eventbus
app.UseFakeMessagingDashboard();
app.Services.GetRequiredService<IFeiShuNotificationService>().Send("Application started");
}
}