-
Notifications
You must be signed in to change notification settings - Fork 680
Expand file tree
/
Copy pathHttpResponseMessageExtensions.cs
More file actions
66 lines (59 loc) · 3.06 KB
/
HttpResponseMessageExtensions.cs
File metadata and controls
66 lines (59 loc) · 3.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
using System.Net;
using System.Net.Http;
namespace ModelContextProtocol;
/// <summary>
/// Extension methods for <see cref="HttpResponseMessage"/>.
/// </summary>
internal static class HttpResponseMessageExtensions
{
private const int MaxResponseBodyLength = 1024;
/// <summary>
/// Throws an <see cref="HttpRequestException"/> if the <see cref="HttpResponseMessage.IsSuccessStatusCode"/> property is <see langword="false"/>.
/// Unlike <see cref="HttpResponseMessage.EnsureSuccessStatusCode"/>, this method includes the response body in the exception message
/// to help diagnose issues when the server returns error details in the response body.
/// </summary>
/// <param name="response">The HTTP response message to check.</param>
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
/// <exception cref="HttpRequestException">The response status code does not indicate success.</exception>
public static async Task EnsureSuccessStatusCodeWithResponseBodyAsync(this HttpResponseMessage response, CancellationToken cancellationToken = default)
{
if (!response.IsSuccessStatusCode)
{
string? responseBody = null;
try
{
using var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
cts.CancelAfter(TimeSpan.FromSeconds(5));
responseBody = await response.Content.ReadAsStringAsync(cts.Token).ConfigureAwait(false);
if (responseBody.Length > MaxResponseBodyLength)
{
responseBody = responseBody.Substring(0, MaxResponseBodyLength) + "...";
}
}
catch
{
// Ignore all errors reading the response body (e.g., stream closed, timeout, cancellation) - we'll throw without it.
}
throw CreateHttpRequestException(response, responseBody);
}
}
/// <summary>
/// Creates an <see cref="HttpRequestException"/> for a non-success response, including the response body in the message.
/// </summary>
/// <param name="response">The HTTP response message.</param>
/// <param name="responseBody">The response body content, if available.</param>
/// <returns>An <see cref="HttpRequestException"/> with the response details.</returns>
public static HttpRequestException CreateHttpRequestException(HttpResponseMessage response, string? responseBody)
{
int statusCodeInt = (int)response.StatusCode;
string message = string.IsNullOrEmpty(responseBody)
? $"Response status code does not indicate success: {statusCodeInt} ({response.ReasonPhrase})."
: $"Response status code does not indicate success: {statusCodeInt} ({response.ReasonPhrase}). Response body: {responseBody}";
#if NET
return new HttpRequestException(message, inner: null, response.StatusCode);
#else
return new HttpRequestException(message);
#endif
}
}