fengling-gateway/Program.cs

114 lines
3.4 KiB
C#

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Serilog;
using Yarp.ReverseProxy.Configuration;
using Yarp.ReverseProxy.LoadBalancing;
using YarpGateway.Config;
using YarpGateway.Data;
using YarpGateway.DynamicProxy;
using YarpGateway.LoadBalancing;
using YarpGateway.Middleware;
using YarpGateway.Services;
using StackExchange.Redis;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog(
(context, services, configuration) =>
configuration
.ReadFrom.Configuration(context.Configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext()
);
builder.Services.Configure<JwtConfig>(builder.Configuration.GetSection("Jwt"));
builder.Services.Configure<RedisConfig>(builder.Configuration.GetSection("Redis"));
builder.Services.AddSingleton(sp => sp.GetRequiredService<IOptions<RedisConfig>>().Value);
builder.Services.AddDbContextFactory<GatewayDbContext>(options =>
options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))
);
builder.Services.AddSingleton<DatabaseRouteConfigProvider>();
builder.Services.AddSingleton<DatabaseClusterConfigProvider>();
builder.Services.AddSingleton<IRouteCache, RouteCache>();
builder.Services.AddSingleton<IRedisConnectionManager, RedisConnectionManager>();
builder.Services.AddSingleton<IConnectionMultiplexer>(sp =>
{
var config = sp.GetRequiredService<RedisConfig>();
var connectionOptions = ConfigurationOptions.Parse(config.ConnectionString);
connectionOptions.AbortOnConnectFail = false;
connectionOptions.ConnectRetry = 3;
connectionOptions.ConnectTimeout = 5000;
connectionOptions.SyncTimeout = 3000;
connectionOptions.DefaultDatabase = config.Database;
var connection = ConnectionMultiplexer.Connect(connectionOptions);
connection.ConnectionFailed += (sender, e) =>
{
Serilog.Log.Error(e.Exception, "Redis connection failed");
};
connection.ConnectionRestored += (sender, e) =>
{
Serilog.Log.Information("Redis connection restored");
};
return connection;
});
builder.Services.AddSingleton<ILoadBalancingPolicy, DistributedWeightedRoundRobinPolicy>();
builder.Services.AddSingleton<DynamicProxyConfigProvider>();
builder.Services.AddSingleton<IProxyConfigProvider>(sp => sp.GetRequiredService<DynamicProxyConfigProvider>());
var corsSettings = builder.Configuration.GetSection("Cors");
builder.Services.AddCors(options =>
{
var allowAnyOrigin = corsSettings.GetValue<bool>("AllowAnyOrigin");
var allowedOrigins = corsSettings.GetSection("AllowedOrigins").Get<string[]>() ?? Array.Empty<string>();
options.AddPolicy("AllowFrontend", policy =>
{
if (allowAnyOrigin)
{
policy.AllowAnyOrigin();
}
else
{
policy.WithOrigins(allowedOrigins);
}
policy.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseCors("AllowFrontend");
app.UseMiddleware<JwtTransformMiddleware>();
app.UseMiddleware<TenantRoutingMiddleware>();
app.MapControllers();
app.MapReverseProxy();
await app.Services.GetRequiredService<IRouteCache>().InitializeAsync();
try
{
Log.Information("Starting YARP Gateway");
app.Run();
}
catch (Exception ex)
{
Log.Fatal(ex, "Application terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}