2025-04-06 17:56:12 +03:30

123 lines
4.4 KiB
C#

using System.Threading.RateLimiting;
using BuildingBlocks.Core;
using BuildingBlocks.Exception;
using BuildingBlocks.HealthCheck;
using BuildingBlocks.Jwt;
using BuildingBlocks.Logging;
using BuildingBlocks.Mapster;
using BuildingBlocks.MassTransit;
using BuildingBlocks.OpenApi;
using BuildingBlocks.OpenTelemetryCollector;
using BuildingBlocks.PersistMessageProcessor;
using BuildingBlocks.ProblemDetails;
using BuildingBlocks.Web;
using Figgle;
using FluentValidation;
using Microsoft.AspNetCore.Mvc;
using Serilog;
namespace Api.Extensions;
public static class SharedInfrastructureExtensions
{
public static WebApplicationBuilder AddSharedInfrastructure(this WebApplicationBuilder builder)
{
builder.Host.UseDefaultServiceProvider(
(context, options) =>
{
// Service provider validation
// ref: https://andrewlock.net/new-in-asp-net-core-3-service-provider-validation/
options.ValidateScopes = context.HostingEnvironment.IsDevelopment() ||
context.HostingEnvironment.IsStaging() ||
context.HostingEnvironment.IsEnvironment("tests");
options.ValidateOnBuild = true;
});
var appOptions = builder.Services.GetOptions<AppOptions>(nameof(AppOptions));
Console.WriteLine(FiggleFonts.Standard.Render(appOptions.Name));
builder.AddCustomSerilog(builder.Environment);
builder.Services.AddScoped<ICurrentUserProvider, CurrentUserProvider>();
builder.Services.AddJwt();
builder.Services.AddTransient<AuthHeaderHandler>();
builder.Services.AddPersistMessageProcessor();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddControllers();
builder.Services.AddAspnetOpenApi();
builder.Services.AddCustomVersioning();
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<IEventDispatcher, EventDispatcher>();
builder.Services.AddCustomMassTransit(
builder.Environment,
TransportType.InMemory,
AppDomain.CurrentDomain.GetAssemblies());
builder.Services.Configure<ApiBehaviorOptions>(
options => options.SuppressModelStateInvalidFilter = true);
builder.Services.AddRateLimiter(
options =>
{
options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(
httpContext =>
RateLimitPartition.GetFixedWindowLimiter(
partitionKey: httpContext.User.Identity?.Name ??
httpContext.Request.Headers.Host.ToString(),
factory: partition => new FixedWindowRateLimiterOptions
{
AutoReplenishment = true,
PermitLimit = 10,
QueueLimit = 0,
Window = TimeSpan.FromMinutes(1)
}));
});
builder.AddCustomObservability();
builder.Services.AddCustomHealthCheck();
builder.Services.AddGrpc(
options =>
{
options.Interceptors.Add<GrpcExceptionInterceptor>();
});
builder.Services.AddEasyCaching(options => { options.UseInMemory(builder.Configuration, "mem"); });
builder.Services.AddValidatorsFromAssemblies(AppDomain.CurrentDomain.GetAssemblies());
builder.Services.AddCustomMapster(AppDomain.CurrentDomain.GetAssemblies());
builder.Services.AddProblemDetails();
return builder;
}
public static WebApplication UserSharedInfrastructure(this WebApplication app)
{
var appOptions = app.Configuration.GetOptions<AppOptions>(nameof(AppOptions));
app.UseCustomProblemDetails();
app.UseCustomObservability();
app.UseCustomHealthCheck();
app.UseSerilogRequestLogging(
options =>
{
options.EnrichDiagnosticContext = LogEnrichHelper.EnrichFromRequest;
});
app.UseCorrelationId();
app.UseRateLimiter();
app.MapGet("/", x => x.Response.WriteAsync(appOptions.Name));
if (app.Environment.IsDevelopment())
{
app.UseAspnetOpenApi();
}
return app;
}
}