ASP.NET Core Web API中使用Flurl的OnError检查自定义响应头问题
问题根因分析
- OnError事件触发逻辑限制:Flurl默认仅在响应状态码≥400时才会触发OnError相关事件,若对接系统返回200等成功状态码但在头中携带错误信息,你的处理逻辑根本不会执行。
- 双处理器冲突:你同时为
OnErrorAsync和OnError赋值,Flurl运行时只会执行其中一个处理器,可能导致异步逻辑未正确运行。
- 双处理器冲突:你同时为
- 响应对象未完全更新:你仅修改了
FlurlCall.HttpResponseMessage属性,但Flurl上层调用常用的IFlurlResponse相关缓存属性没有同步更新,会导致上层拿到的还是原始响应。
- 响应对象未完全更新:你仅修改了
- 解码逻辑无异常捕获:Base64解码、JSON反序列化、
Split("\"")[1]索引取值的逻辑都可能抛出未处理异常,一旦异常触发会直接中断自定义处理流程,回到Flurl默认逻辑。
- 解码逻辑无异常捕获:Base64解码、JSON反序列化、
ExceptionHandled设置错误:你设置了ExceptionHandled = false,Flurl会继续抛出FlurlHttpException,若上层代码未正确捕获该异常,中间件的全局异常处理可能直接返回空的204响应。
修复方案
- 替换OnError事件为全局
AfterCallAsync拦截器,不管响应状态码是什么都优先检查自定义错误头。 - 移除同步
OnError处理器的配置,仅保留异步实现。 - 为解码逻辑添加异常捕获,避免处理流程中断。
- 优化错误消息提取逻辑,避免索引越界。
- 同步更新FlurlCall的相关属性,根据业务需要决定是否吞掉异常。
修正后代码示例
处理逻辑
/// <summary> /// 全局拦截响应,检查自定义错误消息头并替换响应内容 /// </summary> public static async Task HandleCustomErrorHeaderAsync(FlurlCall call) { try { // 不管状态码,先检查是否存在自定义错误头 if (call.Response?.Headers.TryGetFirst("Messages", out var message) == true) { // 解码消息 var messageBytes = Convert.FromBase64String(message); var decodedMessage = JsonSerializer.Deserialize<Message>(Encoding.UTF8.GetString(messageBytes)); // 安全提取错误消息 string errorMsg = null; if (decodedMessage?.RawMessage != null) { var parts = decodedMessage.RawMessage.Split('"'); if (parts.Length >= 2) { errorMsg = parts[1]; } } errorMsg ??= await call.Response.GetStringAsync(); // 构造新的响应 var newResponse = new HttpResponseMessage(HttpStatusCode.BadRequest) { RequestMessage = call.HttpRequestMessage, Content = new StringContent(errorMsg, System.Text.Encoding.UTF8, "application/json") }; // 同步更新FlurlCall所有关联的响应属性 call.HttpResponseMessage = newResponse; call.Response = new FlurlResponse(newResponse); // 若不需要Flurl抛出异常,设置ExceptionHandled = true call.ExceptionHandled = true; } } catch (Exception ex) { // 自定义处理逻辑出错时不要影响原有响应流程,可在这里添加日志记录 System.Diagnostics.Debug.WriteLine($"处理自定义错误头失败:{ex.Message}"); } }
Flurl配置
FlurlHttp.Configure(settings => { // 只保留异步拦截器,替换原有OnError配置 settings.AfterCallAsync = HandleCustomErrorHeaderAsync; // 其他原有配置保留即可 });
内容的提问来源于stack exchange,提问作者thebugsdontwork
相关产品推荐
相关产品推荐

