From c6cd1c3e3fe6f939723792ac9c1016186f3be654 Mon Sep 17 00:00:00 2001 From: Ryan Wang Date: Thu, 19 Mar 2026 12:22:19 +1100 Subject: [PATCH 1/2] handle re-adding the header to the same request --- .../src/Requests/BaseRestClientRequest.cs | 4 ++- src/RestClient/RestClient/src/RestClient.cs | 1 - .../RestClient/test/RestClientRequestTests.cs | 26 +++++++++++++++++++ .../RestClient/test/RestClientTests.cs | 4 +-- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/RestClient/RestClient/src/Requests/BaseRestClientRequest.cs b/src/RestClient/RestClient/src/Requests/BaseRestClientRequest.cs index 835a10a..9b1209c 100644 --- a/src/RestClient/RestClient/src/Requests/BaseRestClientRequest.cs +++ b/src/RestClient/RestClient/src/Requests/BaseRestClientRequest.cs @@ -37,11 +37,13 @@ public abstract class BaseRestClientRequest(HttpMethod method, string public void AddHeader(string key, string value) { + _headers.Remove(key); // no-op if it does not exist _headers.Add(key, value); } public void AddHeader(string key, IEnumerable values) { + _headers.Remove(key); // no-op if it does not exist _headers.Add(key, values); } @@ -53,7 +55,7 @@ public void AddBody(object body) _content = body; return; - bool MethodSupportsBody(HttpMethod method) + static bool MethodSupportsBody(HttpMethod method) { return method == HttpMethod.Post || #if NETCOREAPP2_1_OR_GREATER diff --git a/src/RestClient/RestClient/src/RestClient.cs b/src/RestClient/RestClient/src/RestClient.cs index 69c05c8..7a1539f 100644 --- a/src/RestClient/RestClient/src/RestClient.cs +++ b/src/RestClient/RestClient/src/RestClient.cs @@ -162,7 +162,6 @@ private static HttpClient CreateClient(RestClientOptions options) PrepareHttpClient(httpClient, options); - return httpClient; } diff --git a/src/RestClient/RestClient/test/RestClientRequestTests.cs b/src/RestClient/RestClient/test/RestClientRequestTests.cs index 5cc7474..bfe253c 100644 --- a/src/RestClient/RestClient/test/RestClientRequestTests.cs +++ b/src/RestClient/RestClient/test/RestClientRequestTests.cs @@ -73,6 +73,32 @@ public void AddBody_GetRequest_ThrowsException() Assert.Equal("Cannot add body to GET", ex.Message); } + [Fact] + public void AddHeader_SingleValue_SameHeaderTwice_DoesNotThrow() + { + const string key = "X-Test-Header"; + const string value = "TestValue"; + + var request = new RestClientRequest(HttpMethod.Post, "test"); + request.AddHeader(key, value); + request.AddHeader(key, value); + + Assert.Single(request.Headers); + } + + [Fact] + public void AddHeader_MultipleValues_SameHeaderTwice_DoesNotThrow() + { + const string key = "X-Test-Header"; + string[] values = ["TestValue1", "TestValue2"]; + + var request = new RestClientRequest(HttpMethod.Post, "test"); + request.AddHeader(key, values); + request.AddHeader(key, values); + + Assert.Single(request.Headers); + } + private class TestSerializer : ISerializer { public string Format => "test"; diff --git a/src/RestClient/RestClient/test/RestClientTests.cs b/src/RestClient/RestClient/test/RestClientTests.cs index 5cc8acc..0e08139 100644 --- a/src/RestClient/RestClient/test/RestClientTests.cs +++ b/src/RestClient/RestClient/test/RestClientTests.cs @@ -214,7 +214,7 @@ public async Task ExecuteAsync_DefaultUserAgentSet_RequestContainsDefaultUserAge ItExpr.IsAny(), ItExpr.IsAny() ) - .Callback((request, token) => + .Callback((request, _) => { userAgentHeader = request.Headers.UserAgent.ToString(); }) @@ -244,4 +244,4 @@ protected override async ValueTask> ParseResponseAsyn return new RestClientResponse(message, await message.Content.ReadAsStringAsync()); } } -} \ No newline at end of file +} From eccf8b8d9cc0b099e2d12e488e158d99c9828e9f Mon Sep 17 00:00:00 2001 From: Ryan Wang Date: Thu, 19 Mar 2026 14:40:39 +1100 Subject: [PATCH 2/2] add new AddOrUpdateHeader to set header and have AuthenticateAsync to call it --- .../Authenticators/OAuth/src/OAuthAuthenticator.cs | 6 +++--- .../src/Authentication/BasicAccessAuthenticator.cs | 6 +++--- .../src/Authentication/HeaderAuthenticator.cs | 6 +++--- .../RestClient/src/Requests/BaseRestClientRequest.cs | 12 +++++++++++- .../RestClient/src/Requests/IClientRequest.cs | 4 +++- .../RestClient/test/RestClientRequestTests.cs | 12 ++++++------ 6 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/RestClient/Authenticators/OAuth/src/OAuthAuthenticator.cs b/src/RestClient/Authenticators/OAuth/src/OAuthAuthenticator.cs index 68b5e88..44ecfcd 100644 --- a/src/RestClient/Authenticators/OAuth/src/OAuthAuthenticator.cs +++ b/src/RestClient/Authenticators/OAuth/src/OAuthAuthenticator.cs @@ -1,4 +1,4 @@ -namespace ClickView.Extensions.RestClient.Authenticators.OAuth; +namespace ClickView.Extensions.RestClient.Authenticators.OAuth; using System; using System.Collections.Generic; @@ -56,7 +56,7 @@ public virtual async Task AuthenticateAsync(IClientRequest request, Cancellation return; } - request.AddHeader("Authorization", "Bearer " + oAuthToken); + request.AddOrUpdateHeader("Authorization", "Bearer " + oAuthToken); } protected void AddTokenSource(ITokenSource tokenSource) @@ -116,4 +116,4 @@ protected IAuthenticatorEndpointFactory CreateEndpointFactory(string endpoint) return new DefaultEndpointFactory(Options.Endpoints); } -} \ No newline at end of file +} diff --git a/src/RestClient/RestClient/src/Authentication/BasicAccessAuthenticator.cs b/src/RestClient/RestClient/src/Authentication/BasicAccessAuthenticator.cs index b9664c4..e69409c 100644 --- a/src/RestClient/RestClient/src/Authentication/BasicAccessAuthenticator.cs +++ b/src/RestClient/RestClient/src/Authentication/BasicAccessAuthenticator.cs @@ -1,4 +1,4 @@ -namespace ClickView.Extensions.RestClient.Authentication; +namespace ClickView.Extensions.RestClient.Authentication; using System; using System.Text; @@ -24,7 +24,7 @@ public BasicAccessAuthenticator(string userId, string password) public Task AuthenticateAsync(IClientRequest request, CancellationToken token = default) { - request.AddHeader("Authorization", $"Basic {_encoded}"); + request.AddOrUpdateHeader("Authorization", $"Basic {_encoded}"); return Task.CompletedTask; } @@ -33,4 +33,4 @@ private static string ToBase64(string s) var bytes = Encoding.UTF8.GetBytes(s); return Convert.ToBase64String(bytes); } -} \ No newline at end of file +} diff --git a/src/RestClient/RestClient/src/Authentication/HeaderAuthenticator.cs b/src/RestClient/RestClient/src/Authentication/HeaderAuthenticator.cs index 0fb99ab..9eeeaca 100644 --- a/src/RestClient/RestClient/src/Authentication/HeaderAuthenticator.cs +++ b/src/RestClient/RestClient/src/Authentication/HeaderAuthenticator.cs @@ -1,4 +1,4 @@ -namespace ClickView.Extensions.RestClient.Authentication; +namespace ClickView.Extensions.RestClient.Authentication; using System.Threading; using System.Threading.Tasks; @@ -20,8 +20,8 @@ public HeaderAuthenticator(string key, string value) public Task AuthenticateAsync(IClientRequest request, CancellationToken token = default) { - request.AddHeader(_key, _value); + request.AddOrUpdateHeader(_key, _value); return Task.CompletedTask; } -} \ No newline at end of file +} diff --git a/src/RestClient/RestClient/src/Requests/BaseRestClientRequest.cs b/src/RestClient/RestClient/src/Requests/BaseRestClientRequest.cs index 9b1209c..535667f 100644 --- a/src/RestClient/RestClient/src/Requests/BaseRestClientRequest.cs +++ b/src/RestClient/RestClient/src/Requests/BaseRestClientRequest.cs @@ -37,11 +37,21 @@ public abstract class BaseRestClientRequest(HttpMethod method, string public void AddHeader(string key, string value) { - _headers.Remove(key); // no-op if it does not exist _headers.Add(key, value); } public void AddHeader(string key, IEnumerable values) + { + _headers.Add(key, values); + } + + public void AddOrUpdateHeader(string key, string value) + { + _headers.Remove(key); // no-op if it does not exist + _headers.Add(key, value); + } + + public void AddOrUpdateHeader(string key, IEnumerable values) { _headers.Remove(key); // no-op if it does not exist _headers.Add(key, values); diff --git a/src/RestClient/RestClient/src/Requests/IClientRequest.cs b/src/RestClient/RestClient/src/Requests/IClientRequest.cs index 23e262e..416ffc2 100644 --- a/src/RestClient/RestClient/src/Requests/IClientRequest.cs +++ b/src/RestClient/RestClient/src/Requests/IClientRequest.cs @@ -11,5 +11,7 @@ public interface IClientRequest void AddHeader(string key, string value); void AddHeader(string key, IEnumerable values); + void AddOrUpdateHeader(string key, string value); + void AddOrUpdateHeader(string key, IEnumerable values); void AddBody(object body); -} \ No newline at end of file +} diff --git a/src/RestClient/RestClient/test/RestClientRequestTests.cs b/src/RestClient/RestClient/test/RestClientRequestTests.cs index bfe253c..054d6b3 100644 --- a/src/RestClient/RestClient/test/RestClientRequestTests.cs +++ b/src/RestClient/RestClient/test/RestClientRequestTests.cs @@ -74,27 +74,27 @@ public void AddBody_GetRequest_ThrowsException() } [Fact] - public void AddHeader_SingleValue_SameHeaderTwice_DoesNotThrow() + public void AddOrUpdateHeader_SingleValue_SameHeaderTwice_DoesNotThrow() { const string key = "X-Test-Header"; const string value = "TestValue"; var request = new RestClientRequest(HttpMethod.Post, "test"); - request.AddHeader(key, value); - request.AddHeader(key, value); + request.AddOrUpdateHeader(key, value); + request.AddOrUpdateHeader(key, value); Assert.Single(request.Headers); } [Fact] - public void AddHeader_MultipleValues_SameHeaderTwice_DoesNotThrow() + public void AddOrUpdateHeader_MultipleValues_SameHeaderTwice_DoesNotThrow() { const string key = "X-Test-Header"; string[] values = ["TestValue1", "TestValue2"]; var request = new RestClientRequest(HttpMethod.Post, "test"); - request.AddHeader(key, values); - request.AddHeader(key, values); + request.AddOrUpdateHeader(key, values); + request.AddOrUpdateHeader(key, values); Assert.Single(request.Headers); }