后端API设计【免费下载链接】RestSharpSimple REST and HTTP API Client for .NET项目地址https://gitcode.com/gh_mirrors/re/RestSharp点击查看免费下载导读本文以 RestSharp v112 官方错误处理文档为主体结合仓库源码RestClientOptions.cs、RestResponseBase.cs、RestClient.Async.cs 等深入讲解RestResponse.ResponseStatus的语义规则、RestClientOptions中三个异常抛出配置项、不同 API 扩展方法之间的抛/不抛差异以及如何利用ErrorMessage/ErrorException快速定位传输层、反序列化层与超时类故障。读完本文你将能够根据业务场景精确设计 RestSharp 的错误处理策略做到该抛就抛、该查就查。一、ResponseStatus先理解 RestSharp 眼中的错误是什么RestSharp 对请求结果的判定并不等同于 HTTP 状态码。它的核心概念是ResponseStatus枚举定义在 Enum.cs 中共有五个取值取值含义None请求尚未发出响应对象的初始状态见 RestResponseBase.csCompleted请求正常完成——底层返回了成功状态码或返回了404 Not FoundError网络传输错误断网、DNS 解析失败等或非 404 的服务端错误TimedOut请求超时超过RestRequest.Timeout或客户端默认超时时间Aborted操作被取消且原因不是超时如显式取消CancellationToken原文档给出的判定规则可以概括为两句话只要发生网络传输错误网络断开、DNS 解析失败等或任意非 404 的服务端错误ResponseStatus都会被置为Error其余情况包括 API 返回 404都保持Completed。也就是说404 被 RestSharp 视为请求流程正常走完而非错误。如果你需要拿到服务器实际返回的 HTTP 状态码请读取RestResponse.StatusCodeRestResponseBase.cs。原文档特别强调Status属性是请求是否完成的指示器它与API 业务层是否出错是相互独立的两个维度。1.1 从源码看判定规则CalculateResponseStatus 委托这一默认规则并非硬编码在响应构造流程里而是由一个可定制的委托CalculateResponseStatus驱动其默认实现在 RestClientOptions.cspublic CalculateResponseStatus CalculateResponseStatus { get; set; } httpResponse httpResponse.IsSuccessStatusCode || httpResponse.StatusCode HttpStatusCode.NotFound ? ResponseStatus.Completed : ResponseStatus.Error;当请求成功返回时RestResponse.FromHttpResponse 会调用该委托来填充ResponseStatusResponseStatus options.CalculateResponseStatus(httpResponse),这意味着如果你需要自定义什么算错误的判定例如把 429 也视为业务正常返回可以通过替换该委托实现。这是理解 RestSharp 错误模型的一个关键切入点——判定规则是策略化的而非写死的。1.2 IsSuccessful最常用的一句话判成功基于StatusCode与ResponseStatus的组合RestResponseBase.cs 还提供了便捷属性public bool IsSuccessful IsSuccessStatusCode ResponseStatus ResponseStatus.Completed;即HTTP 状态码表示成功且没有其他错误反序列化、超时等。官方注释也明确ResponseStatus只反映传输与框架层错误HTTP 错误仍会以Completed返回应改查StatusCode。二、默认行为不抛异常错误以属性形式交付原文档明确指出正常情况下RestSharp 在请求失败时不会抛出异常。错误信息被包装进响应对象的两个属性中定义在 RestResponseBase.csErrorMessage错误的人类可读描述ErrorException完整的原始异常对象。响应对象还保留了Request引用RestResponseBase.cs官方注释建议在ResponseStatus异常时用它辅助调试。从 RestClient.Async.cs 的GetErrorResponse可以看到错误属性的填充逻辑static RestResponse GetErrorResponse(RestRequest request, Exception exception, CancellationToken timeoutToken) { var timedOut exception is OperationCanceledException TimedOut(); var response new RestResponse(request) { ResponseStatus exception is OperationCanceledException ? timedOut ? ResponseStatus.TimedOut : ResponseStatus.Aborted : ResponseStatus.Error, ErrorMessage timedOut ? The request timed out. : exception.GetBaseException().Message, ErrorException exception }; return response; }由此可以推断几个值得注意的细节超时请求的ResponseStatus为TimedOut且ErrorMessage固定为The request timed out.判断依据是取消令牌触发或异常消息包含HttpClient.Timeout。其他传输异常的ErrorMessage取GetBaseException().Message即直接暴露最底层根因例如真正的 TLS 失败原因而不是An error occurred while sending the request这类包装消息完整异常链仍可通过ErrorException取得。取消请求非超时对应ResponseStatus.Aborted。提示客户端有一个默认超时_defaultTimeout TimeSpan.FromSeconds(100)见 RestClient.Async.cs可在 RestClientOptions.cs 的Timeout属性或请求级RestRequest.Timeout上覆盖。三、按需开启抛出RestClientOptions 的三个配置项默认不抛异常、给属性的设计偏向防御式编程但有些场景下你更希望让异常直接冒泡。原文档给出了三个可在RestClientOptions上配置的属性它们会作用于该客户端实例发起的所有请求属性默认值行为FailOnDeserializationErrortrue改变反序列化失败但响应仍算成功、Data为空的默认行为。设为true时RestSharp 会把反序列化失败视为错误并将ResponseStatus置为ErrorThrowOnDeserializationErrorfalse改变反序列化失败导致Data为空的默认行为。设为true时反序列化失败会抛出异常ThrowOnAnyErrorfalse设为true时强制 RestSharp 在请求过程或反序列化过程中发生任何错误时抛出异常默认值的补充说明原文档表格侧重行为描述仓库源码给出了确切默认值——FailOnDeserializationError默认为trueRestClientOptions.csThrowOnDeserializationError与ThrowOnAnyError默认为false同文件 L223、L235。即反序列化失败默认就会把状态标为 Error但默认不抛异常。这些属性在 RestClientOptions.cs 中定义注释分别说明ThrowOnDeserializationError控制反序列化失败时抛异常FailOnDeserializationError控制反序列化失败时把状态标为 ErrorThrowOnAnyError则进一步覆盖HttpClient抛异常时是否抛出。3.1 完整示例让客户端在出错时抛异常原文档给出了如下可运行示例配置ThrowOnAnyError true后任何请求或反序列化错误都会以异常形式暴露var options new RestClientOptions(url) { ThrowOnAnyError true }; var client new RestClient(options); var request new RestRequest(resource/{id}).AddUrlSegment(id, 123); // 请求失败会抛异常 var deserialized await client.GetAsyncResponseModel(request); // 请求失败不会抛异常请检查响应对象了解发生了什么 var response await client.ExecuteGetAsyncResponseModel(request);注意ThrowOnAnyError只影响通过该RestClient实例发起的请求不同实例互不影响因此你可以为必须成功的调用链单独创建抛出型客户端为容错轮询场景保留默认客户端。3.2 从源码看三个属性如何起作用ThrowOnAnyError生效于执行链路末端——RestClient.Async.cs 的ExecuteAsync返回前return Options.ThrowOnAnyError ? response.ThrowIfError() : response;ThrowIfError定义在 ResponseThrowExtension.cs本质是把ResponseStatus翻译回异常public RestResponse ThrowIfError() { var exception response.GetException(); return exception ! null ? throw exception : response; }而GetException()RestResponseBase.cs按状态生成对应异常类型ResponseStatus.Aborted new HttpRequestException(Request aborted, ErrorException), ResponseStatus.Error ErrorException, ResponseStatus.TimedOut new TimeoutException(Request timed out, ErrorException),反序列化相关的两个属性则在 RestSerializers.cs 的DeserializeT中生效catch (Exception ex) { if (options.ThrowOnAnyError) throw; if (options.FailOnDeserializationError || options.ThrowOnDeserializationError) response.ResponseStatus ResponseStatus.Error; response.AddException(ex); if (options.ThrowOnDeserializationError) throw new DeserializationException(response, ex); }从这段代码可以清晰看出三个配置项的优先级与组合关系ThrowOnAnyError最高直接重抛原异常随后是状态标记最后是ThrowOnDeserializationError抛出的专用DeserializationException它携带了响应对象便于定位失败上下文。AddExceptionRestResponseBase.cs则负责填充ErrorException与ErrorMessage。补充RestClientOptions中还有一个与错误处理密切相关的属性SetErrorExceptionOnUnsuccessfulStatusCodeRestClientOptions.cs默认true。设为false时客户端不会为非成功状态码的响应填充ErrorException——在你不希望把业务性 4xx/5xx 响应当作异常记录时很有用。四、反序列化失败的边界条件重要提醒:::warning 请注意反序列化失败检测只对抛出异常的反序列化器有效。许多序列化器默认不抛异常而是返回null。此时 RestSharp 无法区分反序列化结果本来就是 null和反序列化失败了因此FailOnDeserializationError/ThrowOnDeserializationError不会生效。 :::原文档这条警告直接决定了上一节配置项是否真正可用。从 RestSerializers.cs 可以看到反序列化入口DeserializeContentT在response.Content null时直接返回default且只在该内容对应注册的反序列化器执行时才可能抛异常。因此使用内置 System.Text.Json 序列化器或Newtonsoft.Json 序列化器时请先确认其是否配置为失败即抛例如自定义转换器或严格模式选项反序列化失败产生的空Data是 RestSharp 无法主动侦测的静默场景这正是警告存在的意义。仓库中错误处理相关测试如 ErrorMessageTests.cs、集成测试 NonProtocolExceptionHandlingTests.cs 与 RequestFailureTests.cs可以佐证上述传输错误进属性、部分场景可配置为抛出的整体行为。五、不同 API 的抛/不抛差异对照表原文档进一步指出不同的方法重载对异常的处理存在差异。核心原因在于GetAsyncT、PostAsyncT等泛型便捷方法不是RestClient的实例方法而是扩展方法它们返回TaskT而不是RestResponse——没有RestResponse对象可以承载ResponseStatus错误状态因此官方选择在请求失败时直接抛出异常。这是API 一致性与可用性之间的权衡诊断问题通常只需要RestResponse的内容而多数情况下抛出的异常本身已足以说明问题。下表完整列出各扩展方法的默认行为并注意默认不抛异常的函数在ThrowOnAnyError true时也会抛出异常。Function出错时是否抛出默认ExecuteAsyncNoExecuteGetAsyncNoExecuteGetAsyncTNoExecutePostAsyncNoExecutePostAsyncTNoExecutePutAsyncNoExecutePutAsyncTNoGetAsyncYesGetAsyncTYesPostAsyncYesPostAsyncTYesPatchAsyncYesPatchAsyncTYesDeleteAsyncYesDeleteAsyncTYesOptionsAsyncYesOptionsAsyncTYesHeadAsyncYesHeadAsyncTYes说明原文档表格覆盖ExecuteAsync、ExecuteGetAsync、ExecutePostAsync、ExecutePutAsync及其泛型版本默认不抛以及Get/Post/Patch/Delete/Options/Head系列默认抛。表格按原文档如实收录。5.1 源码验证GetAsync 确实显式抛出以 GET 为例扩展方法 RestClient.Extensions.Get.cs 的实现明确调用了ThrowIfErrorpublic async TaskRestResponse GetAsync(RestRequest request, CancellationToken cancellationToken default) { var response await client.ExecuteGetAsync(request, cancellationToken).ConfigureAwait(false); return response.ThrowIfError(); }而泛型版本同文件 L118-L121在抛出前还顺带取出了Datapublic async TaskT? GetAsyncT(RestRequest request, CancellationToken cancellationToken default) { var response await client.ExecuteGetAsyncT(request, cancellationToken).ConfigureAwait(false); return response.ThrowIfError().Data; }对比之下ExecuteGetAsync同文件 L26-L27只是单纯转发到client.ExecuteAsync(...)不附加任何抛出逻辑。Execute 前缀 返回响应对象不抛异常无前缀 返回数据/直接抛异常这条规律在仓库所有 HTTP 方法的扩展文件中保持一致。六、JSON 便捷方法同样遵循失败即抛除了上述 HTTP 方法扩展原文档还特别指出所有 JSON 请求便捷函数如GetJsonAsync、PostJsonAsync在 HTTP 调用失败时同样会抛出异常。从源码看这类方法最终都委托给对应的泛型GetAsyncT/PostAsyncT实现例如 RestClient.Extensions.Get.cs 中GetJsonAsync标注为[Obsolete(Use GetAsync instead)]并转发给client.GetAsyncTResponse(resource, cancellationToken)因此自然继承了抛异常语义。在实际使用中新版代码更推荐直接使用GetAsyncT/PostAsyncT取代GetJsonAsync/PostJsonAsync后者已标记过时。七、实战错误处理的推荐检查顺序综合原文档与源码行为面对一个失败的 RestSharp 调用建议按以下顺序排查确认你调用的 API 属于哪一类Execute*系列返回RestResponse请检查响应对象Get*/Post*等便捷方法会直接抛异常请捕获HttpRequestException/TimeoutException/DeserializationException具体类型取决于ResponseStatus见GetException()的映射。若拿到的是RestResponse先看ResponseStatusCompleted说明传输层正常问题在业务层转看StatusCode与IsSuccessfulError/TimedOut/Aborted则继续看ErrorMessage超时为固定文案其他错误为根因消息与ErrorException完整异常链结合Content原始响应体与Request判断是服务器问题还是请求构造问题。按场景选择抛出策略需要异常冒泡、失败即终止的调用链 →ThrowOnAnyError true希望反序列化失败可被感知 → 确认序列化器配置为失败即抛并按需开启FailOnDeserializationError默认已开启或ThrowOnDeserializationError只关心 HTTP 状态、不想把业务 4xx/5xx 当异常 → 保持默认辅以SetErrorExceptionOnUnsuccessfulStatusCode false。八、相关文档与源码索引本文依据的官方文档docs/versioned_docs/version-v112/advanced/error-handling.md最新版见 docs/docs/advanced/error-handling.md配置项定义与默认值src/RestSharp/Options/RestClientOptions.cs响应对象与错误属性src/RestSharp/Response/RestResponseBase.csResponseStatus枚举定义src/RestSharp/Enum.cs执行链路与错误响应构造src/RestSharp/RestClient.Async.cs反序列化错误处理src/RestSharp/Serializers/RestSerializers.cs抛出扩展方法实现src/RestSharp/Response/ResponseThrowExtension.cs扩展方法抛/不抛差异示例src/RestSharp/RestClient.Extensions.Get.cs相关测试test/RestSharp.Tests/ErrorMessageTests.cs、test/RestSharp.Tests.Integrated/NonProtocolExceptionHandlingTests.cs、test/RestSharp.Tests.Integrated/RequestFailureTests.cs赞分享后端API设计【免费下载链接】RestSharpSimple REST and HTTP API Client for .NET项目地址https://gitcode.com/gh_mirrors/re/RestSharp点击查看免费下载相关推荐使用 Apache Airflow Amazon Provider 将任务日志写入 Amazon CloudWatch使用 Apache Airflow Amazon Provider 将任务日志写入 Amazon CloudWatch 将 Airflow 任务日志接入 Ama后端API设计RestSharp 错误处理完全指南ResponseStatus、ThrowOnAnyError 与反序列化异常策略RestSharp 错误处理完全指南ResponseStatus、ThrowOnAnyError 与反序列化异常策略 导读 本文以 RestSharp面向后端API设计PHP-Parser抛出错误器异常错误处理PHP Parser抛出错误器异常错误处理 引言为什么需要专业的错误处理机制 在PHP代码解析过程中语法错误、语义错误和运行时异常是不可避免的。传统的P编译器静态分析代码生成上一篇GitHub 网页版完整指南1 小时掌握建仓库、分支与 Pull Request下一篇TV Bro电视浏览器终极指南如何用遥控器轻松浏览网页的完整解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
