164 lines
5.4 KiB
C#
164 lines
5.4 KiB
C#
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();
|