using System.Net; using System.Text.Json; using Microsoft.Extensions.Logging; namespace LittleShop.Client.Http; public class ErrorHandlingMiddleware : DelegatingHandler { private readonly ILogger _logger; public ErrorHandlingMiddleware(ILogger logger) { _logger = logger; } protected override async Task SendAsync( HttpRequestMessage request, CancellationToken cancellationToken) { try { var response = await base.SendAsync(request, cancellationToken); // Log errors but don't throw - let the service layer handle the response if (!response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(cancellationToken); _logger.LogWarning( "HTTP {StatusCode} for {Method} {Uri}: {Content}", (int)response.StatusCode, request.Method, request.RequestUri, content); // Try to parse error response if (!string.IsNullOrEmpty(content)) { try { var errorResponse = JsonSerializer.Deserialize(content, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); if (errorResponse != null && !string.IsNullOrEmpty(errorResponse.Message)) { // Replace content with structured error message response.Content = new StringContent(errorResponse.Message); } } catch { // If we can't parse the error, leave original content } } } return response; } catch (TaskCanceledException ex) { _logger.LogError(ex, "Request timeout for {Method} {Uri}", request.Method, request.RequestUri); return new HttpResponseMessage(HttpStatusCode.RequestTimeout) { Content = new StringContent("Request timed out"), RequestMessage = request }; } catch (HttpRequestException ex) { _logger.LogError(ex, "Network error for {Method} {Uri}", request.Method, request.RequestUri); return new HttpResponseMessage(HttpStatusCode.ServiceUnavailable) { Content = new StringContent($"Network error: {ex.Message}"), RequestMessage = request }; } catch (Exception ex) { _logger.LogError(ex, "Unexpected error for {Method} {Uri}", request.Method, request.RequestUri); return new HttpResponseMessage(HttpStatusCode.InternalServerError) { Content = new StringContent($"Unexpected error: {ex.Message}"), RequestMessage = request }; } } private class ErrorResponse { public string? Message { get; set; } public string? Error { get; set; } public Dictionary? Errors { get; set; } } }