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.
156 lines
8.0 KiB
156 lines
8.0 KiB
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"); |
|
} |
|
} |
|
}
|
|
|