Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/RestSharp/Extensions/HttpResponseExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
namespace RestSharp.Extensions;

static class HttpResponseExtensions {
public static Exception? MaybeException(this HttpResponseMessage httpResponse)
=> httpResponse.IsSuccessStatusCode
public static Exception? MaybeException(this HttpResponseMessage httpResponse, bool throwOnUnsuccessfulStatusCode)
=> httpResponse.IsSuccessStatusCode || !throwOnUnsuccessfulStatusCode
? null
#if NET
: new HttpRequestException($"Request failed with status code {httpResponse.StatusCode}", null, httpResponse.StatusCode);
Expand Down
1 change: 0 additions & 1 deletion src/RestSharp/Options/ReadOnlyRestClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ namespace RestSharp;
public partial class ReadOnlyRestClientOptions {
public IReadOnlyCollection<Interceptor>? Interceptors { get; private set; }

// partial void CopyAdditionalProperties(RestClientOptions inner);
partial void CopyAdditionalProperties(RestClientOptions inner) => Interceptors = GetInterceptors(inner);

static ReadOnlyCollection<Interceptor>? GetInterceptors(RestClientOptions? options) {
Expand Down
6 changes: 6 additions & 0 deletions src/RestSharp/Options/RestClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@ public RestClientOptions(string baseUrl) : this(new Uri(Ensure.NotEmptyString(ba
/// </summary>
public bool ThrowOnAnyError { get; set; }

/// <summary>
/// When set to false, the client doesn't throw an exception when the response status code is not successful.
/// Default is true.
/// </summary>
public bool ErrorWhenUnsuccessfulStatusCode { get; set; } = true;
Comment thread
alexeyzimarev marked this conversation as resolved.
Outdated

/// <summary>
/// Set to true to allow multiple default parameters with the same name. Default is false.
/// This setting doesn't apply to headers as multiple header values for the same key is allowed.
Expand Down
20 changes: 9 additions & 11 deletions src/RestSharp/Response/RestResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
// limitations under the License.

using System.Diagnostics;
using System.Text;
using RestSharp.Extensions;

// ReSharper disable SuggestBaseTypeForParameter
Expand All @@ -39,12 +38,11 @@ public partial class RestResponse<T>(RestRequest request) : RestResponse(request
[DebuggerDisplay($"{{{nameof(DebuggerDisplay)}()}}")]
public class RestResponse(RestRequest request) : RestResponseBase(request) {
internal static async Task<RestResponse> FromHttpResponse(
HttpResponseMessage httpResponse,
RestRequest request,
Encoding encoding,
CookieCollection? cookieCollection,
CalculateResponseStatus calculateResponseStatus,
CancellationToken cancellationToken
HttpResponseMessage httpResponse,
RestRequest request,
ReadOnlyRestClientOptions options,
CookieCollection? cookieCollection,
CancellationToken cancellationToken
) {
return request.AdvancedResponseWriter?.Invoke(httpResponse, request) ?? await GetDefaultResponse().ConfigureAwait(false);

Expand All @@ -56,7 +54,7 @@ async Task<RestResponse> GetDefaultResponse() {
#endif

var bytes = stream == null ? null : await stream.ReadAsBytes(cancellationToken).ConfigureAwait(false);
var content = bytes == null ? null : await httpResponse.GetResponseString(bytes, encoding);
var content = bytes == null ? null : await httpResponse.GetResponseString(bytes, options.Encoding);

return new(request) {
Content = content,
Expand All @@ -65,11 +63,11 @@ async Task<RestResponse> GetDefaultResponse() {
ContentLength = httpResponse.Content?.Headers.ContentLength,
ContentType = httpResponse.Content?.Headers.ContentType?.MediaType,
Cookies = cookieCollection,
ErrorException = httpResponse.MaybeException(),
ErrorException = httpResponse.MaybeException(options.ErrorWhenUnsuccessfulStatusCode),
Headers = httpResponse.Headers.GetHeaderParameters(),
IsSuccessStatusCode = httpResponse.IsSuccessStatusCode,
RawBytes = bytes,
ResponseStatus = calculateResponseStatus(httpResponse),
ResponseStatus = options.CalculateResponseStatus(httpResponse),
ResponseUri = httpResponse.RequestMessage?.RequestUri,
RootElement = request.RootElement,
Server = httpResponse.Headers.Server.ToString(),
Expand All @@ -83,4 +81,4 @@ async Task<RestResponse> GetDefaultResponse() {
public RestResponse() : this(new()) { }
}

public delegate ResponseStatus CalculateResponseStatus(HttpResponseMessage httpResponse);
public delegate ResponseStatus CalculateResponseStatus(HttpResponseMessage httpResponse);
5 changes: 2 additions & 3 deletions src/RestSharp/RestClient.Async.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ public async Task<RestResponse> ExecuteAsync(RestRequest request, CancellationTo
? await RestResponse.FromHttpResponse(
internalResponse.ResponseMessage!,
request,
Options.Encoding,
Options,
internalResponse.CookieContainer?.GetCookies(internalResponse.Url),
Options.CalculateResponseStatus,
cancellationToken
)
.ConfigureAwait(false)
Expand All @@ -49,7 +48,7 @@ public async Task<RestResponse> ExecuteAsync(RestRequest request, CancellationTo
request.CompletionOption = HttpCompletionOption.ResponseHeadersRead;
var response = await ExecuteRequestAsync(request, cancellationToken).ConfigureAwait(false);

var exception = response.Exception ?? response.ResponseMessage?.MaybeException();
var exception = response.Exception ?? response.ResponseMessage?.MaybeException(Options.ErrorWhenUnsuccessfulStatusCode);

if (exception != null) {
return Options.ThrowOnAnyError ? throw exception : null;
Expand Down
15 changes: 15 additions & 0 deletions test/RestSharp.Tests.Integrated/RequestFailureTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@ public async Task Handles_GET_Request_Errors_With_Response_Type() {
var response = await _client.ExecuteAsync<SuccessResponse>(request);

response.StatusCode.Should().Be(HttpStatusCode.NotFound);
response.IsSuccessStatusCode.Should().BeFalse();
response.ErrorException.Should().NotBeNull();
response.Data.Should().Be(null);
}

[Fact]
public async Task Does_not_throw_on_unsuccessful_status_code_with_option() {
using var client = new RestClient(new RestClientOptions(server.Url!) { ErrorWhenUnsuccessfulStatusCode = false });
var request = new RestRequest("status?code=404");
var response = await client.ExecuteAsync<SuccessResponse>(request);

response.StatusCode.Should().Be(HttpStatusCode.NotFound);
response.IsSuccessStatusCode.Should().BeFalse();
response.ErrorException.Should().BeNull();
response.Data.Should().Be(null);
}

Expand All @@ -29,6 +43,7 @@ public async Task Throws_on_unsuccessful_call() {
using var client = new RestClient(new RestClientOptions(server.Url!) { ThrowOnAnyError = true });
var request = new RestRequest("status?code=500");

// ReSharper disable once AccessToDisposedClosure
var task = () => client.ExecuteAsync<SuccessResponse>(request);
await task.Should().ThrowExactlyAsync<HttpRequestException>();
}
Expand Down
Loading