TRestRequest.Execute遇300及以上状态码抛出EHTTPProtocolException的原因及抑制方法问询
嘿,我来帮你理清这个问题——你遇到的矛盾其实是因为REST组件的异常控制配置没做全,加上对底层异常的处理有细节需要注意。
问题根源分析
你看到的文档描述只覆盖了部分场景:TRestRequest.Execute默认会在非2xx系列的HTTP状态码时抛出EHTTPProtocolException,而你仅设置了restClient.RaiseExceptionOn500 := False——这个属性仅控制5xx状态码是否抛出异常,对4xx等其他错误状态码完全无效。另外,当底层使用THttpClient(也就是你定位到的Rest.HttpClient单元)时,异常会直接从底层抛出,必须通过组件属性配置来抑制。
解决方案
1. 完全禁用REST组件的异常抛出(推荐)
最直接的方法是配置TRESTRequest的RaiseExceptionOnError属性为False,这样无论什么状态码,Execute都不会抛出异常,你可以完全自主通过TRestResponse.StatusCode判断结果:
修改你的代码,在创建restRequest后添加这一行:
restRequest.RaiseExceptionOnError := False;
同时保留restClient.RaiseExceptionOn500 := False;的设置,这样就能完全抑制所有HTTP状态码引发的异常,让你正常处理响应状态。
2. 正确捕获EHTTPProtocolException(如果需要保留异常抛出)
如果你需要在特定场景下保留异常、仅处理它,需要注意两个关键点:
- 必须在
uses中添加REST.HttpClient单元,因为EHTTPProtocolException定义在这个单元里; - 确保
try..except块正确包裹restRequest.Execute调用,并且异常类型匹配。
示例代码:
try restRequest.Execute; except on E: EHTTPProtocolException do begin // 这里处理异常,比如记录日志或忽略后继续执行 Writeln('捕获到HTTP异常: ', E.Message); // 可通过E.StatusCode获取对应的状态码 Writeln('状态码: ', E.StatusCode); end; end;
3. 你的代码修改建议
把创建REST组件后的配置部分调整为:
restRequest.Client := restClient; restRequest.Response := restResponse; restClient.BaseURL := 'https://rustmaps.com/api/v2/maps/' + seed.ToString + '/' + size.ToString; restClient.RaiseExceptionOn500 := False; restRequest.RaiseExceptionOnError := False; // 新增这行关键配置
这样修改后,restRequest.Execute就不会再抛出异常,你可以正常通过restResponse.Status.SuccessOK_200、restResponse.Status.ClientErrorDuplicate_409等属性处理不同的响应状态。
内容的提问来源于stack exchange,提问作者Adriaan

