diff --git a/src/RestSharp/Options/RestClientOptions.cs b/src/RestSharp/Options/RestClientOptions.cs
index 9b28c66ad..1c81ecd84 100644
--- a/src/RestSharp/Options/RestClientOptions.cs
+++ b/src/RestSharp/Options/RestClientOptions.cs
@@ -180,10 +180,9 @@ public RestClientOptions(string baseUrl) : this(new Uri(Ensure.NotEmptyString(ba
public CookieContainer? CookieContainer { get; set; }
///
- /// Maximum request duration in milliseconds. When the request timeout is specified using ,
- /// the lowest value between the client timeout and request timeout will be used.
+ /// Request duration. Used when the request timeout is not specified using ,
///
- public int MaxTimeout { get; set; }
+ public TimeSpan? Timeout { get; set; }
///
/// Default encoding to use when no encoding is specified in the content type header.
diff --git a/src/RestSharp/Request/RestRequest.cs b/src/RestSharp/Request/RestRequest.cs
index 16be4837d..6213e5573 100644
--- a/src/RestSharp/Request/RestRequest.cs
+++ b/src/RestSharp/Request/RestRequest.cs
@@ -139,7 +139,7 @@ public RestRequest(Uri resource, Method method = Method.Get)
///
/// Custom request timeout
///
- public int Timeout { get; set; }
+ public TimeSpan? Timeout { get; set; }
///
/// The Resource URL to make the request against.
@@ -163,7 +163,7 @@ public RestRequest(Uri resource, Method method = Method.Get)
///
/// Used by the default deserializers to determine where to start deserializing from.
- /// Can be used to skip container or root elements that do not have corresponding deserialzation targets.
+ /// Can be used to skip container or root elements that do not have corresponding deserialization targets.
///
public string? RootElement { get; set; }
diff --git a/src/RestSharp/RestClient.Async.cs b/src/RestSharp/RestClient.Async.cs
index 4655c0780..ba28ff3d0 100644
--- a/src/RestSharp/RestClient.Async.cs
+++ b/src/RestSharp/RestClient.Async.cs
@@ -19,6 +19,8 @@
namespace RestSharp;
public partial class RestClient {
+ // Default HttpClient timeout
+ public TimeSpan DefaultTimeout = TimeSpan.FromSeconds(100);
///
public async Task ExecuteAsync(RestRequest request, CancellationToken cancellationToken = default) {
using var internalResponse = await ExecuteRequestAsync(request, cancellationToken).ConfigureAwait(false);
@@ -113,7 +115,7 @@ async Task ExecuteRequestAsync(RestRequest request, CancellationTo
message.Headers.Host = Options.BaseHost;
message.Headers.CacheControl = request.CachePolicy ?? Options.CachePolicy;
- using var timeoutCts = new CancellationTokenSource(request.Timeout > 0 ? request.Timeout : int.MaxValue);
+ using var timeoutCts = new CancellationTokenSource(request.Timeout ?? Options.Timeout ?? DefaultTimeout);
using var cts = CancellationTokenSource.CreateLinkedTokenSource(timeoutCts.Token, cancellationToken);
var ct = cts.Token;
diff --git a/src/RestSharp/RestClient.cs b/src/RestSharp/RestClient.cs
index c41c41953..da8ce9a19 100644
--- a/src/RestSharp/RestClient.cs
+++ b/src/RestSharp/RestClient.cs
@@ -33,6 +33,7 @@ namespace RestSharp;
///
/// Client to translate RestRequests into Http requests and process response result
///
+// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global
public partial class RestClient : IRestClient {
///
/// Content types that will be sent in the Accept header. The list is populated from the known serializers.
@@ -55,11 +56,6 @@ public string[] AcceptedContentTypes {
///
public DefaultParameters DefaultParameters { get; }
- [Obsolete("Use RestClientOptions.Authenticator instead")]
- public IAuthenticator? Authenticator => Options.Authenticator;
-
- // set => Options.Authenticator = value;
-
///
/// Creates an instance of RestClient using the provided
///
@@ -226,7 +222,8 @@ public RestClient(
: this(new HttpClient(handler, disposeHandler), true, configureRestClient, configureSerialization) { }
static void ConfigureHttpClient(HttpClient httpClient, RestClientOptions options) {
- if (options.MaxTimeout > 0) httpClient.Timeout = TimeSpan.FromMilliseconds(options.MaxTimeout);
+ // We will use Options.Timeout in ExecuteAsInternalAsync method
+ httpClient.Timeout = Timeout.InfiniteTimeSpan;
if (options.Expect100Continue != null) httpClient.DefaultRequestHeaders.ExpectContinue = options.Expect100Continue;
}
@@ -257,6 +254,7 @@ static void ConfigureHttpMessageHandler(HttpClientHandler handler, RestClientOpt
handler.AllowAutoRedirect = options.FollowRedirects;
#if NET
+ // ReSharper disable once InvertIf
if (!OperatingSystem.IsBrowser() && !OperatingSystem.IsIOS() && !OperatingSystem.IsTvOS()) {
#endif
if (handler.SupportsProxy) handler.Proxy = options.Proxy;
@@ -276,12 +274,12 @@ void ConfigureSerializers(ConfigureSerialization? configureSerialization) {
}
void ConfigureDefaultParameters(RestClientOptions options) {
- if (options.UserAgent != null) {
- if (!options.AllowMultipleDefaultParametersWithSameName
- && DefaultParameters.Any(parameter => parameter.Type == ParameterType.HttpHeader && parameter.Name == KnownHeaders.UserAgent))
- DefaultParameters.RemoveParameter(KnownHeaders.UserAgent, ParameterType.HttpHeader);
- DefaultParameters.AddParameter(Parameter.CreateParameter(KnownHeaders.UserAgent, options.UserAgent, ParameterType.HttpHeader));
- }
+ if (options.UserAgent == null) return;
+
+ if (!options.AllowMultipleDefaultParametersWithSameName
+ && DefaultParameters.Any(parameter => parameter.Type == ParameterType.HttpHeader && parameter.Name == KnownHeaders.UserAgent))
+ DefaultParameters.RemoveParameter(KnownHeaders.UserAgent, ParameterType.HttpHeader);
+ DefaultParameters.AddParameter(Parameter.CreateParameter(KnownHeaders.UserAgent, options.UserAgent, ParameterType.HttpHeader));
}
readonly bool _disposeHttpClient;
diff --git a/test/RestSharp.Tests.Integrated/NonProtocolExceptionHandlingTests.cs b/test/RestSharp.Tests.Integrated/NonProtocolExceptionHandlingTests.cs
index bac3d052d..981b552ee 100644
--- a/test/RestSharp.Tests.Integrated/NonProtocolExceptionHandlingTests.cs
+++ b/test/RestSharp.Tests.Integrated/NonProtocolExceptionHandlingTests.cs
@@ -45,7 +45,7 @@ public async Task Handles_HttpClient_Timeout_Error() {
public async Task Handles_Server_Timeout_Error() {
using var client = new RestClient(_server.Url!);
- var request = new RestRequest("timeout") { Timeout = 500 };
+ var request = new RestRequest("404") { Timeout = TimeSpan.FromMilliseconds(500) };
var response = await client.ExecuteAsync(request);
response.ErrorException.Should().BeOfType();
@@ -56,7 +56,7 @@ public async Task Handles_Server_Timeout_Error() {
public async Task Handles_Server_Timeout_Error_With_Deserializer() {
using var client = new RestClient(_server.Url!);
- var request = new RestRequest("timeout") { Timeout = 500 };
+ var request = new RestRequest("timeout") { Timeout = TimeSpan.FromMilliseconds(500) };
var response = await client.ExecuteAsync(request);
response.Data.Should().BeNull();
diff --git a/test/RestSharp.Tests.Integrated/PutTests.cs b/test/RestSharp.Tests.Integrated/PutTests.cs
index ac26c9144..dbe5907e6 100644
--- a/test/RestSharp.Tests.Integrated/PutTests.cs
+++ b/test/RestSharp.Tests.Integrated/PutTests.cs
@@ -31,7 +31,7 @@ public async Task Can_Timeout_PUT_Async() {
var request = new RestRequest("/timeout", Method.Put).AddBody("Body_Content");
// Half the value of ResponseHandler.Timeout
- request.Timeout = 200;
+ request.Timeout = TimeSpan.FromMilliseconds(200);
var response = await _client.ExecuteAsync(request);
diff --git a/test/RestSharp.Tests.Integrated/RequestTests.cs b/test/RestSharp.Tests.Integrated/RequestTests.cs
index 81aafbb53..70c7661fd 100644
--- a/test/RestSharp.Tests.Integrated/RequestTests.cs
+++ b/test/RestSharp.Tests.Integrated/RequestTests.cs
@@ -55,7 +55,7 @@ public async Task Can_Timeout_GET_Async() {
var request = new RestRequest("timeout").AddBody("Body_Content");
// Half the value of ResponseHandler.Timeout
- request.Timeout = 200;
+ request.Timeout = TimeSpan.FromMilliseconds(200);
var response = await _client.ExecuteAsync(request);