using Fake.AspNetCore; using Fake.AspNetCore.Auditing; using Fake.AspNetCore.Mvc; using Fake.AspNetCore.Mvc.Conventions; using Fake.Autofac; using Fake.Modularity; using Fake.Security.Claims; using FluentValidation.AspNetCore; using Hangfire; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Authorization; using Microsoft.OpenApi.Models; using OpenTelemetry.Resources; using OpenTelemetry.Trace; using TrackCenter.Application; using TrackCenter.Application.Hangfire; using TrackCenter.Domain.Extensions; 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))] 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(options => { options.ApplicationServices2Controller(); }); // 配置签名验证选项 services.Configure(configuration.GetSection("SignatureValidation")); // 全局授权配置:所有接口默认需要授权 services.AddMvc(options => { var policy = new AuthorizationPolicyBuilder() .RequireAuthenticatedUser() .Build(); options.Filters.Add(new AuthorizeFilter(policy)); // 添加签名验证过滤器 options.Filters.Add(); }).AddNewtonsoftJson(); //Json格式化全局处理 context.Services.Configure(options => { options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization. CamelCasePropertyNamesContractResolver(); // 首字母小写(驼峰样式) options.SerializerSettings.Converters.Add(new DateTimeJsonConverter("yyyy-MM-dd HH:mm:ss")); options.SerializerSettings.Converters.Add(new LongJsonConverter()); }); services.AddFakeSwaggerGen(options => { options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme() { Description = "JWT授权数据将在请求头中进行传输,在下方输入Bearer {token} 即可,注意两者之间有空格", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey }); options.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference() { Id = "Bearer", Type = ReferenceType.SecurityScheme } }, [] } }); }) .AddFakeAspNetCoreAuditing(); 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() ?? []) .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); services.AddFakeJwtAuthentication(); // 添加授权服务 services.AddAuthorization(); } public override void ConfigureApplication(ApplicationConfigureContext context) { var app = context.GetWebApplication(); app.Use(async (httpContext, next) => { httpContext.Request.EnableBuffering(); await next.Invoke(); }); app.UseFakeExceptionHandling(); app.MapControllers(); // Configure the HTTP request pipeline. app.UseFakeSwagger(); app.UseRouting(); app.UseCors(DefaultCorsPolicyName); // todo: 缺乏配置 app.UseHangfireDashboard("/hangfire", new DashboardOptions { DisplayStorageConnectionString = false, IgnoreAntiforgeryToken = true, AppPath = "", PrefixPath = "", DashboardTitle = "轨迹预警任务", Authorization = [new AnonymousHangfireAuthorizationFilter()] }); LogHelper.Info("Application started", true); } public override void Shutdown(ApplicationShutdownContext context) { LogHelper.Info("Application stoped", true); } }