Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ One way of doing it is to use `RestClient` constructors that accept an instance

- `BaseAddress` will be used to set the base address of the `HttpClient` instance if base address is not set there already.
- `MaxTimeout`
- `UserAgent` will be set if the `User-Agent` header is not set on the `HttpClient` instance already.
- `UserAgent` will be added to the `RestClient.DefaultParameters` list as a HTTP header. This will be added to each request made by the `RestClient`, and the `HttpClient` instance will not be modified. This is to allow the `HttpClient` instance to be reused for scenarios where different `User-Agent` headers are required.
- `Expect100Continue`

Another option is to use a simple HTTP client factory as described [above](#simple-factory).
Expand Down
23 changes: 15 additions & 8 deletions src/RestSharp/RestClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public RestClient(

ConfigureSerializers(configureSerialization);
Options = new ReadOnlyRestClientOptions(options);
DefaultParameters = new DefaultParameters(Options);

if (useClientFactory) {
_disposeHttpClient = false;
Expand All @@ -83,15 +84,14 @@ public RestClient(
HttpClient = GetClient();
}

DefaultParameters = new DefaultParameters(Options);

HttpClient GetClient() {
var handler = new HttpClientHandler();
ConfigureHttpMessageHandler(handler, Options);
var finalHandler = options.ConfigureMessageHandler?.Invoke(handler) ?? handler;

var httpClient = new HttpClient(finalHandler);
ConfigureHttpClient(httpClient, options);
ConfigureDefaultParameters(options);
configureDefaultHeaders?.Invoke(httpClient.DefaultRequestHeaders);
return httpClient;
}
Expand Down Expand Up @@ -181,7 +181,10 @@ public RestClient(
Options = new ReadOnlyRestClientOptions(opt);
DefaultParameters = new DefaultParameters(Options);

if (options != null) ConfigureHttpClient(httpClient, options);
if (options != null) {
ConfigureHttpClient(httpClient, options);
ConfigureDefaultParameters(options);
}
}

/// <summary>
Expand Down Expand Up @@ -218,11 +221,6 @@ public RestClient(
static void ConfigureHttpClient(HttpClient httpClient, RestClientOptions options) {
if (options.MaxTimeout > 0) httpClient.Timeout = TimeSpan.FromMilliseconds(options.MaxTimeout);

if (options.UserAgent != null &&
httpClient.DefaultRequestHeaders.UserAgent.All(x => $"{x.Product?.Name}/{x.Product?.Version}" != options.UserAgent)) {
httpClient.DefaultRequestHeaders.TryAddWithoutValidation(KnownHeaders.UserAgent, options.UserAgent);
}

if (options.Expect100Continue != null) httpClient.DefaultRequestHeaders.ExpectContinue = options.Expect100Continue;
}

Expand Down Expand Up @@ -270,6 +268,15 @@ void ConfigureSerializers(ConfigureSerialization? configureSerialization) {
AcceptedContentTypes = Serializers.GetAcceptedContentTypes();
}

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));
}
}

readonly bool _disposeHttpClient;

bool _disposed;
Expand Down
39 changes: 30 additions & 9 deletions test/RestSharp.Tests/RestClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,20 +118,41 @@ public void Should_use_new_httpClient_instance() {
}

[Fact]
public void ConfigureHttpClient_does_not_duplicate_user_agent_for_same_client() {
public void ConfigureDefaultParameters_sets_user_agent_new_httpClient_instance() {
// arrange
var clientOptions = new RestClientOptions();

// act
var restClient = new RestClient(clientOptions);

//assert
Assert.Single(
restClient.DefaultParameters,
parameter => parameter.Type == ParameterType.HttpHeader &&
parameter.Name == KnownHeaders.UserAgent &&
parameter.Value is string valueAsString &&
valueAsString == clientOptions.UserAgent);

Assert.Empty(restClient.HttpClient.DefaultRequestHeaders.UserAgent);
}

[Fact]
public void ConfigureDefaultParameters_sets_user_agent_given_httpClient_instance() {
// arrange
var httpClient = new HttpClient();
var clientOptions = new RestClientOptions();

// act
var unused = new RestClient(httpClient, clientOptions);
var dummy = new RestClient(httpClient, clientOptions);
var restClient = new RestClient(httpClient, clientOptions);

// assert
Assert.Contains(
httpClient.DefaultRequestHeaders.UserAgent,
agent => $"{agent.Product.Name}/{agent.Product.Version}" == clientOptions.UserAgent
);
Assert.Single(httpClient.DefaultRequestHeaders.UserAgent);
//assert
Assert.Single(
restClient.DefaultParameters,
parameter => parameter.Type == ParameterType.HttpHeader &&
parameter.Name == KnownHeaders.UserAgent &&
parameter.Value is string valueAsString &&
valueAsString == clientOptions.UserAgent);

Assert.Empty(httpClient.DefaultRequestHeaders.UserAgent);
}
}