You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
8.0 KiB
157 lines
8.0 KiB
3 weeks ago
|
using Microsoft.AspNetCore.Http;
|
||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||
|
using Microsoft.Extensions.Logging;
|
||
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
using System.Security.Policy;
|
||
|
using System.Text;
|
||
|
using System.Threading.Tasks;
|
||
|
|
||
|
namespace ReZero.SuperAPI
|
||
|
{
|
||
|
public class DynamicApiManager : IDynamicApi
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Determines if the given URL is a valid API endpoint.
|
||
|
/// </summary>
|
||
|
/// <param name="url">The URL to check.</param>
|
||
|
/// <returns>True if the URL is a valid API endpoint, false otherwise.</returns>
|
||
|
public bool IsApi(string url)
|
||
|
{
|
||
|
var db = App.Db;
|
||
|
var isAnyUrl = CacheManager<ZeroInterfaceList>.Instance.GetList()
|
||
|
.Any(it =>
|
||
|
it!.Url!.ToLower() == url.ToLower()||
|
||
|
(it.OriginalUrl!=null&&url.ToLower().StartsWith(it.OriginalUrl.ToLower()))
|
||
|
);
|
||
|
return isAnyUrl;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Writes the response for the given HTTP context.
|
||
|
/// </summary>
|
||
|
/// <param name="context">The HTTP context.</param>
|
||
|
public async Task WriteAsync(HttpContext context)
|
||
|
{
|
||
|
var helper = new DynamicApiHelper();
|
||
|
var requestMethodString = context.Request.Method;
|
||
|
HttpRequestMethod requestMethod;
|
||
|
if (helper.IsHttpMethod(requestMethodString, out requestMethod))
|
||
|
{
|
||
|
await WriteAsyncSuccess(context, helper, requestMethod);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
await WriteError(context);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Writes the response for a successful API request.
|
||
|
/// </summary>
|
||
|
/// <param name="context">The HTTP context.</param>
|
||
|
/// <param name="helper">The dynamic API helper.</param>
|
||
|
/// <param name="requestMethod">The HTTP request method.</param>
|
||
|
private static async Task WriteAsyncSuccess(HttpContext context, DynamicApiHelper helper, HttpRequestMethod requestMethod)
|
||
|
{
|
||
|
var handler = helper.GetHandler(requestMethod, context);
|
||
|
var db = App.Db;
|
||
|
var path = context.Request.Path.ToString()?.ToLower();
|
||
|
var interInfo = CacheManager<ZeroInterfaceList>
|
||
|
.Instance.GetList()
|
||
|
.Where(it =>
|
||
|
it.Url!.ToLower() == path
|
||
|
||
|
||
|
(it.OriginalUrl != null && path!.ToLower().StartsWith(it.OriginalUrl.ToLower()))
|
||
|
)?.First();
|
||
|
interInfo = db.Utilities.TranslateCopy(interInfo);
|
||
|
var dynamicInterfaceContext = new InterfaceContext() { InterfaceType = InterfaceType.DynamicApi, HttpContext = context, InterfaceInfo = interInfo };
|
||
|
if (interInfo == null)
|
||
|
{
|
||
|
var message = TextHandler.GetCommonText($"未找到内置接口 {path} ,请在表ZeroInterfaceList中查询", $"No built-in interface {path} is found. Query in the table ZeroInterfaceList");
|
||
|
context.Response.StatusCode = 500;
|
||
|
await context.Response.WriteAsync(message);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
DataService dataService = new DataService();
|
||
|
interInfo!.DataModel!.ApiId = interInfo.Id;
|
||
|
interInfo!.DataModel!.ResultType = interInfo.DataModel?.ResultType;
|
||
|
interInfo!.DataModel!.Sql = interInfo.DataModel?.Sql;
|
||
|
interInfo!.DataModel!.DataBaseId = interInfo.DataModel?.DataBaseId ?? 0;
|
||
|
dataService.BindHttpParameters.Bind(interInfo.DataModel, context, path, !string.IsNullOrEmpty(interInfo.OriginalUrl), interInfo);
|
||
|
dynamicInterfaceContext.DataModel = interInfo.DataModel;
|
||
|
var service = DependencyInjection.DependencyResolver.Provider;
|
||
|
dynamicInterfaceContext.ServiceProvider = service;
|
||
|
interInfo.DataModel!.ServiceProvider = service;
|
||
|
await SuperAPIModule._apiOptions!.InterfaceOptions!.SuperApiAop!.OnExecutingAsync(dynamicInterfaceContext);
|
||
|
await InstanceManager.AuthorizationAsync(context, dynamicInterfaceContext);
|
||
|
var data = await dataService.ExecuteAction(interInfo.DataModel!);
|
||
|
data = GetUserInfo(path, interInfo, data);
|
||
|
SetDataToAop(dynamicInterfaceContext, data);
|
||
|
await SuperAPIModule._apiOptions!.InterfaceOptions!.SuperApiAop!.OnExecutedAsync(dynamicInterfaceContext);
|
||
|
var resultModel = interInfo.CustomResultModel ?? new ResultModel();
|
||
|
resultModel.OutPutData = interInfo.DataModel?.OutPutData;
|
||
|
data = new ResultService().GetResult(data!, resultModel);
|
||
|
if (IsNoSystemPublicApi(interInfo, context))
|
||
|
data = SuperAPIModule._apiOptions?.InterfaceOptions?.MergeDataToStandardDtoFunc?.Invoke(data) ?? data;
|
||
|
var json = JsonHelper.SerializeObject(data, SuperAPIModule._apiOptions!.InterfaceOptions?.JsonSerializerSettings);
|
||
|
context.Response.ContentType = PubConst.DataSource_ApplicationJson;
|
||
|
await context.Response.WriteAsync(json);
|
||
|
}
|
||
|
catch (Exception ex)
|
||
|
{
|
||
|
ReZero.DependencyInjection.DependencyResolver.GetLogger().LogInformation(ex.Message);
|
||
|
object data = new ErrorResponse { message = ex.Message };
|
||
|
if (IsNoSystemPublicApi(interInfo, context))
|
||
|
data = SuperAPIModule._apiOptions?.InterfaceOptions?.MergeDataToStandardDtoFunc?.Invoke(data) ?? data;
|
||
|
context.Response.ContentType = PubConst.DataSource_ApplicationJson;
|
||
|
await context.Response.WriteAsync(JsonHelper.SerializeObject(data, SuperAPIModule._apiOptions!.InterfaceOptions?.JsonSerializerSettings));
|
||
|
dynamicInterfaceContext.Exception = ex;
|
||
|
await SuperAPIModule._apiOptions!.InterfaceOptions!.SuperApiAop!.OnErrorAsync(dynamicInterfaceContext);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static bool IsNoSystemPublicApi(ZeroInterfaceList interInfo, HttpContext context)
|
||
|
{
|
||
|
var query = context.Request.Query;
|
||
|
var supportCustomDto = query.ContainsKey("supportCustomDto") && query["supportCustomDto"].ToString().ToLower() == "true";
|
||
|
return ((interInfo.Url?.ToLower()?.StartsWith("/public/") != true) && interInfo.Id != InterfaceListInitializerProvider.GetTokenId) || supportCustomDto;
|
||
|
}
|
||
|
|
||
|
private static void SetDataToAop(InterfaceContext dynamicInterfaceContext, object? data)
|
||
|
{
|
||
|
if (dynamicInterfaceContext.DataModel != null)
|
||
|
dynamicInterfaceContext.DataModel.Data = data;
|
||
|
}
|
||
|
|
||
|
private static object? GetUserInfo(string? path, ZeroInterfaceList interInfo, object? data)
|
||
|
{
|
||
|
if (path == PubConst.Jwt_GetJwtInfo)
|
||
|
{
|
||
|
data = interInfo?.DataModel?.ClaimList;
|
||
|
if (interInfo?.DataModel?.ClaimList?.Any()!=true)
|
||
|
{
|
||
|
throw new Exception(TextHandler.GetCommonText("你没有启用JWT授权或者没有配置Claim", "You did not enable JWT authorization or did not configure Claim"));
|
||
|
}
|
||
|
}
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// Writes the response for an invalid API request.
|
||
|
/// </summary>
|
||
|
/// <param name="context">The HTTP context.</param>
|
||
|
private static async Task WriteError(HttpContext context)
|
||
|
{
|
||
|
context.Response.StatusCode = 400; // Bad Request
|
||
|
await context.Response.WriteAsync("Invalid request method");
|
||
|
}
|
||
|
}
|
||
|
}
|