<commit_before>using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Security.Authentication;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace TypedRest.Errors
{
    /// <summary>
    /// Handles errors in HTTP responses by mapping status codes to common exception types.
    /// </summary>
    public class DefaultErrorHandler : IErrorHandler
    {
        public async Task HandleAsync(HttpResponseMessage response)
        {
            if (response.IsSuccessStatusCode) return;

            string message = $"{response.RequestMessage?.RequestUri} responded with {(int)response.StatusCode} {response.ReasonPhrase}";
            string? body = null;

            if (response.Content != null)
            {
                body = await response.Content.ReadAsStringAsync().NoContext();
                message = ExtractJsonMessage(response, body) ?? message;
            }

            var exception = MapException(response.StatusCode, message);
            exception.SetHttpResponseHeaders(response.Headers);
            if (body != null) exception.SetHttpResponseBody(body);
            throw exception;
        }

        private static string? ExtractJsonMessage(HttpResponseMessage response, string body)
        {
            if (response.Content.Headers.ContentType?.MediaType == "application/json")
            {<commit_msg>Improved content-type detection in DefaultErrorHandler<commit_after>using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Security.Authentication;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace TypedRest.Errors
{
    /// <summary>
    /// Handles errors in HTTP responses by mapping status codes to common exception types.
    /// </summary>
    public class DefaultErrorHandler : IErrorHandler
    {
        public async Task HandleAsync(HttpResponseMessage response)
        {
            if (response.IsSuccessStatusCode) return;

            string message = $"{response.RequestMessage?.RequestUri} responded with {(int)response.StatusCode} {response.ReasonPhrase}";
            string? body = null;

            if (response.Content != null)
            {
                body = await response.Content.ReadAsStringAsync().NoContext();
                message = ExtractJsonMessage(response, body) ?? message;
            }

            var exception = MapException(response.StatusCode, message);
            exception.SetHttpResponseHeaders(response.Headers);
            if (body != null) exception.SetHttpResponseBody(body);
            throw exception;
        }

        private static string? ExtractJsonMessage(HttpResponseMessage response, string body)
        {
            string? mediaType = response.Content.Headers.ContentType?.MediaType;
            if (mediaType == "application/json" || (mediaType != null && mediaType.EndsWith("+json")))
            {
{'fraction_non_alphanumeric': 0.09457671957671958, 'fraction_numerical': 0.0, 'mean_word_length': 2.7207872078720787, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6334884', 'n_tokens_mistral': 736, 'n_tokens_neox': 725, 'n_words': 186}