Compare commits

...
5 Commits
Author SHA1 Message Date
xrain e53048a980 update option 2024-12-23 22:11:00 +08:00
xrain bbc2806995 add origin response attribute 2024-12-23 20:34:38 +08:00
xrain 404a638d5e add filter 2024-12-23 20:26:21 +08:00
xrain e27d5e1c77 fix data 2024-09-08 14:42:51 +08:00
xrain 6af68da3eb timeout rpc supported 2024-09-05 15:06:44 +08:00
9 changed files with 92 additions and 24 deletions
+8
View File
@@ -0,0 +1,8 @@
using System;
namespace SimApi.Attributes;
[AttributeUsage(AttributeTargets.Method)]
public class OriginResponseAttribute : Attribute
{
}
+2 -9
View File
@@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using SimApi.Helpers;
namespace SimApi.Communications; namespace SimApi.Communications;
@@ -36,15 +37,7 @@ public class SimApiBaseResponse(int code = 200, string message = "成功")
/// <returns></returns> /// <returns></returns>
public override string ToString() public override string ToString()
{ {
return JsonSerializer.Serialize(this, new JsonSerializerOptions return SimApiUtil.Json(this);
{
IgnoreReadOnlyProperties = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Converters =
{
new JsonStringEnumConverter()
}
});
} }
} }
+5
View File
@@ -36,6 +36,11 @@ public class SimApiOptions
/// default: true /// default: true
/// </summary> /// </summary>
public bool EnableSimApiException { get; set; } = true; public bool EnableSimApiException { get; set; } = true;
/// <summary>
/// 启用返回结果拦截
/// </summary>
public bool EnableSimApiResponseFilter { get; set; } = true;
/// <summary> /// <summary>
/// 开启S3兼容的存储系统。 /// 开启S3兼容的存储系统。
+34
View File
@@ -0,0 +1,34 @@
using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using SimApi.Attributes;
using SimApi.Communications;
namespace SimApi.Helpers;
public class SimApiResponseFilter : IResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
if (context.ActionDescriptor.EndpointMetadata.Any(meta => meta is OriginResponseAttribute))
{
return;
}
context.Result = context.Result switch
{
// 检查结果是否为 null
null => new OkObjectResult(new SimApiBaseResponse()),
ObjectResult { Value: SimApiBaseResponse simApiBaseResponse } =>
new OkObjectResult(simApiBaseResponse),
ObjectResult objectResult => new OkObjectResult(new SimApiBaseResponse<object>(objectResult.Value!)),
EmptyResult => new OkObjectResult(new SimApiBaseResponse()),
_ => context.Result
};
}
public void OnResultExecuted(ResultExecutedContext context)
{
}
}
+4 -7
View File
@@ -1,5 +1,5 @@
using System; using System;
using System.Linq; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using SimApi.Communications; using SimApi.Communications;
@@ -27,12 +27,11 @@ public class SimApiExceptionMiddleware(RequestDelegate next, ILogger<SimApiExcep
switch (context.Response.StatusCode) switch (context.Response.StatusCode)
{ {
case 200: case 200:
break;
case 404:
throw new SimApiException(context.Response.StatusCode, "请求的接口不存在");
case 301: case 301:
case 302: case 302:
break; break;
case 404:
throw new SimApiException(context.Response.StatusCode, "请求的接口不存在");
default: default:
throw new SimApiException(context.Response.StatusCode); throw new SimApiException(context.Response.StatusCode);
} }
@@ -42,7 +41,6 @@ public class SimApiExceptionMiddleware(RequestDelegate next, ILogger<SimApiExcep
response = string.IsNullOrEmpty(ex.Message) response = string.IsNullOrEmpty(ex.Message)
? new SimApiBaseResponse(ex.Code) ? new SimApiBaseResponse(ex.Code)
: new SimApiBaseResponse(ex.Code, ex.Message); : new SimApiBaseResponse(ex.Code, ex.Message);
ErrorResponse(context, response); ErrorResponse(context, response);
} }
catch (Exception ex) catch (Exception ex)
@@ -61,9 +59,8 @@ public class SimApiExceptionMiddleware(RequestDelegate next, ILogger<SimApiExcep
/// <param name="response"></param> /// <param name="response"></param>
private static void ErrorResponse(HttpContext context, SimApiBaseResponse response) private static void ErrorResponse(HttpContext context, SimApiBaseResponse response)
{ {
if (context.Response.HasStarted) return;
context.Response.StatusCode = 200; context.Response.StatusCode = 200;
context.Response.Headers.Append("Content-Type", "application/json"); context.Response.Headers.Append("Content-Type", "application/json");
context.Response.WriteAsync(response.ToString()); context.Response.WriteAsync(response.ToString()).Wait();
} }
} }
-2
View File
@@ -19,9 +19,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Helpers\"/>
<Folder Include="Communications\"/> <Folder Include="Communications\"/>
<Folder Include="Middlewares\"/>
<Folder Include="Exceptions\"/> <Folder Include="Exceptions\"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+29
View File
@@ -1,4 +1,8 @@
using System; using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text.Json;
using SimApi.Helpers; using SimApi.Helpers;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@@ -7,6 +11,7 @@ using SimApi.Middlewares;
using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using SimApi.Attributes;
using SimApi.CoceSdk; using SimApi.CoceSdk;
using SimApi.Configurations; using SimApi.Configurations;
using SimApi.Logger; using SimApi.Logger;
@@ -53,6 +58,19 @@ public static class SimApiExtensions
if (simApiOptions.EnableSynapse) if (simApiOptions.EnableSynapse)
{ {
builder.AddSingleton<Synapse>(); builder.AddSingleton<Synapse>();
//自动依赖注入
var stackTrace = new StackTrace();
var callingMethod = stackTrace.GetFrame(stackTrace.FrameCount - 1)?.GetMethod();
var assembly = callingMethod?.DeclaringType?.Assembly;
var types = assembly?.GetTypes() ?? [];
foreach (var type in types)
{
var methodsWithSynapse = type.GetMethods()
.Where(m => m.GetCustomAttribute<SynapseRpcAttribute>() != null ||
m.GetCustomAttribute<SynapseEventAttribute>() != null);
if (!methodsWithSynapse.Any()) continue;
builder.AddScoped(type);
}
} }
// 使用SimApiDoc // 使用SimApiDoc
@@ -192,6 +210,12 @@ public static class SimApiExtensions
builder.AddSingleton<SimApiStorage>(); builder.AddSingleton<SimApiStorage>();
} }
if (simApiOptions.EnableSimApiResponseFilter)
{
builder.AddControllers(opt => opt.Filters.Add<SimApiResponseFilter>())
.AddJsonOptions(opt => opt.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase);
}
builder.AddSingleton(simApiOptions); builder.AddSingleton(simApiOptions);
return builder; return builder;
} }
@@ -211,6 +235,11 @@ public static class SimApiExtensions
builder.Services.GetService<SimApiStorage>(); builder.Services.GetService<SimApiStorage>();
} }
if (options.EnableSimApiResponseFilter)
{
logger.LogInformation("开始配置SimApiResponseFilter...");
}
if (options.EnableCoceSdk) if (options.EnableCoceSdk)
{ {
logger.LogInformation("开始配置CoceAppSdk...\nApi入口: {ApiUrl}\nAuth入口:{AuthUrl}n\nAppId: {AppId}", logger.LogInformation("开始配置CoceAppSdk...\nApi入口: {ApiUrl}\nAuth入口:{AuthUrl}n\nAppId: {AppId}",
+4 -2
View File
@@ -40,7 +40,8 @@ public partial class Synapse
Client!.SubscribeAsync(rcSubOpts).Wait(); Client!.SubscribeAsync(rcSubOpts).Wait();
} }
private string? FireRpc(string app, string action, object? param, Dictionary<string, string>? headers = null) private string? FireRpc(string app, string action, object? param, Dictionary<string, string>? headers = null,
int? timeout = null)
{ {
string paramJson; string paramJson;
if (param is string strParam) if (param is string strParam)
@@ -77,7 +78,8 @@ public partial class Synapse
string response; string response;
try try
{ {
if (tcs.Task.Wait(Options.RpcTimeout * 1000)) timeout ??= Options.RpcTimeout;
if (tcs.Task.Wait(timeout.Value * 1000))
{ {
response = tcs.Task.Result; response = tcs.Task.Result;
logger.LogDebug( logger.LogDebug(
+6 -4
View File
@@ -88,10 +88,11 @@ public partial class Synapse(SimApiOptions simApiOptions, ILogger<Synapse> logge
/// <param name="method"></param> /// <param name="method"></param>
/// <param name="param"></param> /// <param name="param"></param>
/// <param name="headers"></param> /// <param name="headers"></param>
/// <param name="timeout"></param>
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
/// <returns></returns> /// <returns></returns>
public SimApiBaseResponse<T> Rpc<T>(string appName, string method, dynamic? param = null, public SimApiBaseResponse<T> Rpc<T>(string appName, string method, dynamic? param = null,
Dictionary<string, string>? headers = null) Dictionary<string, string>? headers = null, int? timeout = null)
{ {
var res = new SimApiBaseResponse(500, "Synapse Rpc Client Disabled!"); var res = new SimApiBaseResponse(500, "Synapse Rpc Client Disabled!");
if (Options.DisableRpcClient) if (Options.DisableRpcClient)
@@ -100,7 +101,7 @@ public partial class Synapse(SimApiOptions simApiOptions, ILogger<Synapse> logge
} }
else else
{ {
var data = FireRpc(appName, method, param, headers); var data = FireRpc(appName, method, param, headers, timeout);
res = JsonSerializer.Deserialize<SimApiBaseResponse<T>>(data, SimApiUtil.JsonOption); res = JsonSerializer.Deserialize<SimApiBaseResponse<T>>(data, SimApiUtil.JsonOption);
} }
@@ -114,11 +115,12 @@ public partial class Synapse(SimApiOptions simApiOptions, ILogger<Synapse> logge
/// <param name="method"></param> /// <param name="method"></param>
/// <param name="param"></param> /// <param name="param"></param>
/// <param name="headers"></param> /// <param name="headers"></param>
/// <param name="timeout"></param>
/// <returns></returns> /// <returns></returns>
public SimApiBaseResponse<object> Rpc(string appName, string method, dynamic? param = null, public SimApiBaseResponse<object> Rpc(string appName, string method, dynamic? param = null,
Dictionary<string, string>? headers = null) Dictionary<string, string>? headers = null, int? timeout = null)
{ {
return Rpc<object>(appName, method, param, headers); return Rpc<object>(appName, method, param, headers, timeout);
} }