ql_apimanager_backend/Apimanager_backend/Program.cs

164 lines
5.4 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 Apimanager_backend.Config;
using Apimanager_backend.Data;
using Apimanager_backend.Dtos;
using Apimanager_backend.Filters;
using Apimanager_backend.Filters.ExceptionFilter;
using Apimanager_backend.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Serilog.Sinks.MariaDB.Extensions;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
IConfiguration configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
string? redStr = configuration["Redis:ConnectionString"];
string? constr = configuration.GetConnectionString("DefaultConnection");
//日志服务
/*
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.MariaDB(
connectionString: constr,
tableName: "Logs",
autoCreateTable:true
).CreateLogger();
builder.Host.UseSerilog();
*/
builder.Services.AddDbContext<ApiContext>(option =>
option.UseMySql(constr, MySqlServerVersion.AutoDetect(constr))
);
builder.Services.AddAllService(configuration);
builder.Services.AddControllers(options =>
{
//模型验证
options.Filters.Add<ModelValidationFilter>();
//Exception过滤器
options.Filters.Add<generalExceptionFilter>();
}).ConfigureApiBehaviorOptions(option =>
{
option.SuppressModelStateInvalidFilter = true;
})
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.MaxDepth = 64;
});
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
app.Use(async (ctx, next) =>
{
var controller = ctx.Request.RouteValues["controller"]?.ToString(); // YourController
var action = ctx.Request.RouteValues["action"]?.ToString();
if (controller != "Public" || action != "Invoke")
{
await next();
return;
}
if (ctx.Request.Headers.TryGetValue("Authorization", out var hdr) &&
hdr.ToString().StartsWith("Bearer "))
{
var token = hdr.ToString().Substring("Bearer ".Length).Trim();
var code = ctx.Request.RouteValues["code"]!.ToString()!;
RateLimiterDto rateLimiterDto = new RateLimiterDto();
var userService = ctx.RequestServices.GetRequiredService<IUserService>();
var apiService = ctx.RequestServices.GetRequiredService<IApiService>();
var apiPackageItemService = ctx.RequestServices.GetRequiredService<IApiPackageItemService>();
var userPackageService = ctx.RequestServices.GetRequiredService<IUserPackageService>();
var user = await userService.GetByTokenAsync(token);
var api = await apiService.GetApiInfoByEndpointAsync(code);
var apiPackages = await apiPackageItemService.GetApiPackageItemsByApiIdAsync(api.Id);
if (user == null || apiPackages.Count == 0)
{
ctx.Items["rateLimit"] = null;
}
else
{
var userPackages = await userPackageService.GetUserPackagesByUserIdAsync(user.Id);
if (userPackages.Count == 0)
{
ctx.Items["rateLimit"] = null;
}
// 提取 list2 中的所有 package.id变成 HashSet 提高查找效率
var apipackage1 = new HashSet<int>(apiPackages.Select(x => x.ApiPackage.Id));
var uPackages = userPackages
.Where(x => apipackage1.Contains(x.Package.Id)).ToList();
// 从 list1 中筛选出 user.id 存在于 list2 的项
var commonPackages = uPackages
.Select(x => x.Package)
.ToList();
var package = commonPackages.Count > 0 ? commonPackages.MaxBy(x => x.OneMinuteLimit) : null;
var data = package == null ? null : new RateLimiterDto()
{
UserId = user.Id,
RateLimit = package.OneMinuteLimit
};
ctx.Items["rateLimit"] = data;
ctx.Items["userPackages"] = uPackages;
}
}
else
{
ctx.Items["rateLimit"] = null;
}
if (ctx.Items["rateLimit"] == null)
{
ctx.Response.StatusCode = 429;
ctx.Response.ContentType = "application/json";
await ctx.Response.WriteAsJsonAsync(new ResponseBase<object>()
{
Code = 3003,
Data = null,
Message = "未授权或访问频率受限"
});
return; // ⛔ 不调用 next(),请求终止
}
await next();
return;
});
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
//app.UseHttpsRedirection();
app.UseCors("AllowAll");
app.UseAuthentication();
app.UseAuthorization();
app.UseRateLimiter();
/*
app.Use(async (context, next) =>
{
var controller = context.Request.RouteValues["controller"]?.ToString(); // YourController
var action = context.Request.RouteValues["action"]?.ToString(); // Invoke
var code = context.Request.RouteValues["code"]?.ToString(); // ← 就是你要的 GetUserList
Console.WriteLine($"控制器: {controller}, 实际方法: {code}(映射到 Invoke");
// 你可以根据 code 设置速率限制策略、权限校验等
await next();
});
*/
app.MapControllers();
app.Run();