From b82991bd6d0f660c4d23017999109dffc4effd4a Mon Sep 17 00:00:00 2001 From: Elivo Date: Tue, 10 Mar 2026 10:58:34 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20IApiException=EF=BC=8C?= =?UTF-8?q?=E7=94=A8=E4=BA=8E=E8=87=AA=E5=AE=9A=E4=B9=89=20Response=20?= =?UTF-8?q?=E7=9A=84=20status=20=E5=80=BC=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Apewer/ForbiddenException.cs | 24 ++++++++++++++ Apewer/NotFoundException.cs | 46 +++++++++++++++++++++++++++ Apewer/RedundanceException.cs | 7 +---- Apewer/UnauthorizedException.cs | 5 +-- Apewer/Web/ApiProcessor.cs | 56 ++++++++++++++++++++++++++++----- Apewer/Web/IApiException.cs | 16 ++++++++++ 6 files changed, 139 insertions(+), 15 deletions(-) create mode 100644 Apewer/ForbiddenException.cs create mode 100644 Apewer/NotFoundException.cs create mode 100644 Apewer/Web/IApiException.cs diff --git a/Apewer/ForbiddenException.cs b/Apewer/ForbiddenException.cs new file mode 100644 index 0000000..df1191e --- /dev/null +++ b/Apewer/ForbiddenException.cs @@ -0,0 +1,24 @@ +using Apewer.Web; +using System; + +namespace Apewer +{ + + /// 表示被禁止访问的错误。 + public sealed class ForbiddenException : Exception, IApiException + { + + const string DefaultMessage = "禁止访问。"; + + /// 表示禁止访问的状态。 + public string Status { get => "Forbidden"; } + + /// + public ForbiddenException(string message = DefaultMessage) : base(message.IsEmpty() ? DefaultMessage : message) { } + + /// + public override string ToString() => $" {Message}"; + + } + +} diff --git a/Apewer/NotFoundException.cs b/Apewer/NotFoundException.cs new file mode 100644 index 0000000..3188338 --- /dev/null +++ b/Apewer/NotFoundException.cs @@ -0,0 +1,46 @@ +using Apewer.Web; +using System; + +namespace Apewer +{ + + /// 表示目标资源不存在的错误。 + public class NotFoundException : Exception, IApiException + { + + static string _default = FixMessage(null); + + static string FixMessage(string message) + { + const string Preset = "Resource not found."; + if (message != null) + { + message = message.Trim(); + if (!string.IsNullOrEmpty(message)) return message; + } + + return Preset; + } + + /// 获取或设置默认消息。 + public static string DefaultMessage { get => _default; set => _default = FixMessage(value); } + + /// 状态。 + /// Unauthorized + public virtual string Status { get => "Not Found"; } + + /// 表示目标资源不存在的错误。 + /// 默认消息:Operation is not authorized. + public NotFoundException() : base(DefaultMessage) { } + + /// 表示目标资源不存在的错误。 + /// 默认消息:Operation is not authorized. + public NotFoundException(string message) : base(FixMessage(message)) { } + + /// 表示目标资源不存在的错误。 + /// 默认消息:Operation is not authorized. + public NotFoundException(string message, Exception innerException) : base(FixMessage(message), innerException) { } + + } + +} diff --git a/Apewer/RedundanceException.cs b/Apewer/RedundanceException.cs index c9c8fb3..d17a04f 100644 --- a/Apewer/RedundanceException.cs +++ b/Apewer/RedundanceException.cs @@ -1,9 +1,4 @@ -using Apewer.Internals; -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Runtime.Serialization; -using System.Text; +using System; namespace Apewer { diff --git a/Apewer/UnauthorizedException.cs b/Apewer/UnauthorizedException.cs index 6931754..9c0cc28 100644 --- a/Apewer/UnauthorizedException.cs +++ b/Apewer/UnauthorizedException.cs @@ -1,11 +1,12 @@ -using System; +using Apewer.Web; +using System; namespace Apewer { /// 表示未授权的错误。 /// 默认消息:Operation is not authorized. - public class UnauthorizedException : Exception + public class UnauthorizedException : Exception, IApiException { static string _default = FixMessage(null); diff --git a/Apewer/Web/ApiProcessor.cs b/Apewer/Web/ApiProcessor.cs index 8a70f0a..cf0d26f 100644 --- a/Apewer/Web/ApiProcessor.cs +++ b/Apewer/Web/ApiProcessor.cs @@ -1,4 +1,5 @@ -using Apewer.Network; +using Apewer.Internals; +using Apewer.Network; using System; using System.Collections.Generic; using System.Net; @@ -305,7 +306,17 @@ namespace Apewer.Web if (action != null) { _context.ApiAction = action; - InvokeAction(action); + if (action.Unparallel) + { + UnparallelLocker.InLock(GetUnparallelKey(action.MethodInfo), () => + { + InvokeAction(action); + }); + } + else + { + InvokeAction(action); + } return; } } @@ -438,15 +449,27 @@ namespace Apewer.Web { // 控制器初始化。 var initializer = ApiUtility.GetInitialier(controller); - var match = initializer == null ? true : initializer.Invoke(controller); - if (!match) return; + if (initializer != null) + { + var @continue = true; + UnparallelLocker.InLock(GetUnparallelKey(controller.GetType()), () => + { + @continue = initializer.Invoke(controller); + }); + if (!@continue) return; + } + + // 此应用独立处理,不受反射控制。 if (application.Independent) return; if (function != null) { // 调用 API,获取返回值。 _context.Controller = controller; - Invoke(_context, function.Method, function.Parameters); + UnparallelLocker.InLock(GetUnparallelKey(function.Method), () => + { + Invoke(_context, function.Method, function.Parameters); + }); } else { @@ -454,8 +477,11 @@ namespace Apewer.Web var @default = ApiUtility.GetDefault(controller); if (@default != null) { - @default.Invoke(controller); - return; + UnparallelLocker.InLock(GetUnparallelKey(controller.GetType()), () => + { + @default.Invoke(controller); + return; + }); } // 没有执行任何 Function,尝试枚举。 @@ -803,6 +829,22 @@ namespace Apewer.Web #endregion + #region 不可并行 + + static TextLocker UnparallelLocker = new TextLocker(); + + static string GetUnparallelKey(MethodInfo method) + { + return $"{method.DeclaringType.Assembly.ToString()} | {method.DeclaringType.FullName} | {method.ToString()}"; + } + + static string GetUnparallelKey(Type type) + { + return $"{type.DeclaringType.Assembly.ToString()}"; + } + + #endregion + } } diff --git a/Apewer/Web/IApiException.cs b/Apewer/Web/IApiException.cs new file mode 100644 index 0000000..f6ec856 --- /dev/null +++ b/Apewer/Web/IApiException.cs @@ -0,0 +1,16 @@ +namespace Apewer.Web +{ + + /// 执行 API 时发生的异常。 + public interface IApiException + { + + /// 异常状态。 + string Status { get; } + + /// 错误消息。 + string Message { get; } + + } + +}