diff --git a/src/RestSharp/IRestRequest.cs b/src/RestSharp/IRestRequest.cs index 052ce4f90..f03c12e9a 100644 --- a/src/RestSharp/IRestRequest.cs +++ b/src/RestSharp/IRestRequest.cs @@ -374,9 +374,17 @@ public interface IRestRequest /// /// Name of the header to add /// Value of the header to add - /// + /// This request IRestRequest AddHeader(string name, string value); + /// + /// Shortcut to AddOrUpdateParameter(name, value, HttpHeader) overload + /// + /// Name of the header to add or update + /// Value of the header to add or update + /// This request + IRestRequest AddOrUpdateHeader(string name, string value); + /// /// Uses AddHeader(name, value) in a convenient way to pass /// in multiple headers at once. @@ -384,6 +392,14 @@ public interface IRestRequest /// Key/Value pairs containing the name: value of the headers /// This request IRestRequest AddHeaders(ICollection> headers); + + /// + /// Uses AddOrUpdateHeader(name, value) in a convenient way to pass + /// in multiple headers at once. + /// + /// Key/Value pairs containing the name: value of the headers + /// This request + IRestRequest AddOrUpdateHeaders(ICollection> headers); /// /// Shortcut to AddParameter(name, value, Cookie) overload diff --git a/src/RestSharp/RestRequest.cs b/src/RestSharp/RestRequest.cs index 01bc1d83d..ecdd7703d 100644 --- a/src/RestSharp/RestRequest.cs +++ b/src/RestSharp/RestRequest.cs @@ -384,25 +384,21 @@ public IRestRequest AddOrUpdateParameter(string name, object value, string conte /// public IRestRequest AddHeader(string name, string value) { - static bool InvalidHost(string host) => Uri.CheckHostName(PortSplitRegex.Split(host)[0]) == UriHostNameType.Unknown; - - if (name == "Host" && InvalidHost(value)) - throw new ArgumentException("The specified value is not a valid Host header string.", nameof(value)); - + CheckAndThrowsForInvalidHost(name, value); return AddParameter(name, value, ParameterType.HttpHeader); } /// - public IRestRequest AddHeaders(ICollection> headers) + public IRestRequest AddOrUpdateHeader(string name, string value) { - var duplicateKeys = headers - .GroupBy(pair => pair.Key.ToUpperInvariant()) - .Where(group => group.Count() > 1) - .Select(group => group.Key) - .ToList(); + CheckAndThrowsForInvalidHost(name, value); + return AddOrUpdateParameter(name, value, ParameterType.HttpHeader); + } - if (duplicateKeys.Any()) - throw new ArgumentException($"Duplicate header names exist: {string.Join(", ", duplicateKeys)}"); + /// + public IRestRequest AddHeaders(ICollection> headers) + { + CheckAndThrowsDuplicateKeys(headers); foreach (var pair in headers) { @@ -412,6 +408,19 @@ public IRestRequest AddHeaders(ICollection> headers return this; } + /// + public IRestRequest AddOrUpdateHeaders(ICollection> headers) + { + CheckAndThrowsDuplicateKeys(headers); + + foreach (var pair in headers) + { + AddOrUpdateHeader(pair.Key, pair.Value); + } + + return this; + } + /// public IRestRequest AddCookie(string name, string value) => AddParameter(name, value, ParameterType.Cookie); @@ -486,5 +495,25 @@ public IRestRequest AddDecompressionMethod(DecompressionMethods decompressionMet public IRestRequest AddUrlSegment(string name, object value) => AddParameter(name, value, ParameterType.UrlSegment); IRestRequest AddFile(FileParameter file) => this.With(x => x.Files.Add(file)); + + private static void CheckAndThrowsForInvalidHost(string name, string value) + { + static bool InvalidHost(string host) => Uri.CheckHostName(PortSplitRegex.Split(host)[0]) == UriHostNameType.Unknown; + + if (name == "Host" && InvalidHost(value)) + throw new ArgumentException("The specified value is not a valid Host header string.", nameof(value)); + } + + private static void CheckAndThrowsDuplicateKeys(ICollection> headers) + { + var duplicateKeys = headers + .GroupBy(pair => pair.Key.ToUpperInvariant()) + .Where(group => group.Count() > 1) + .Select(group => group.Key) + .ToList(); + + if (duplicateKeys.Any()) + throw new ArgumentException($"Duplicate header names exist: {string.Join(", ", duplicateKeys)}"); + } } } diff --git a/test/RestSharp.Tests/RequestHeaderTests.cs b/test/RestSharp.Tests/RequestHeaderTests.cs index 3db5788bc..f7f80961a 100644 --- a/test/RestSharp.Tests/RequestHeaderTests.cs +++ b/test/RestSharp.Tests/RequestHeaderTests.cs @@ -29,7 +29,7 @@ public void AddHeaders_SameCaseDuplicatesExist_ThrowsException() [Test] public void AddHeaders_DifferentCaseDuplicatesExist_ThrowsException() { - var headers = new List>() + var headers = new List> { new KeyValuePair("Accept", "application/json"), new KeyValuePair("Accept-Language", "en-us,en;q=0.5"), @@ -46,7 +46,7 @@ public void AddHeaders_DifferentCaseDuplicatesExist_ThrowsException() [Test] public void AddHeaders_NoDuplicatesExist_Has3Headers() { - var headers = new List>() + var headers = new List> { new KeyValuePair("Accept", "application/json"), new KeyValuePair("Accept-Language", "en-us,en;q=0.5"), @@ -64,7 +64,7 @@ public void AddHeaders_NoDuplicatesExist_Has3Headers() [Test] public void AddHeaders_NoDuplicatesExistUsingDictionary_Has3Headers() { - var headers = new Dictionary() + var headers = new Dictionary { { "Accept", "application/json" }, { "Accept-Language", "en-us,en;q=0.5" }, @@ -78,5 +78,122 @@ public void AddHeaders_NoDuplicatesExistUsingDictionary_Has3Headers() Assert.AreEqual(3, httpParameters.Count()); } + + [Test] + public void AddOrUpdateHeader_ShouldUpdateExistingHeader_WhenHeaderExist() + { + // Arrange + var request = new RestRequest(); + request.AddHeader("Accept", "application/xml"); + + // Act + request.AddOrUpdateHeader("Accept", "application/json"); + + // Assert + var headers = request.Parameters.Where(parameter => parameter.Type == ParameterType.HttpHeader).ToArray(); + + Assert.AreEqual("application/json", headers.First(parameter => parameter.Name == "Accept").Value); + Assert.AreEqual(1, headers.Length); + } + + [Test] + public void AddOrUpdateHeader_ShouldUpdateExistingHeader_WhenHeaderDoesNotExist() + { + // Arrange + var request = new RestRequest(); + + // Act + request.AddOrUpdateHeader("Accept", "application/json"); + + // Assert + var headers = request.Parameters.Where(parameter => parameter.Type == ParameterType.HttpHeader).ToArray(); + + Assert.AreEqual("application/json", headers.First(parameter => parameter.Name == "Accept").Value); + Assert.AreEqual(1, headers.Length); + } + + [Test] + public void AddOrUpdateHeaders_ShouldAddHeaders_WhenNoneExists() + { + // Arrange + var headers = new Dictionary + { + { "Accept", "application/json" }, + { "Accept-Language", "en-us,en;q=0.5" }, + { "Keep-Alive", "300" } + }; + + var request = new RestRequest(); + + // Act + request.AddOrUpdateHeaders(headers); + + // Assert + var requestHeaders = request.Parameters.Where(parameter => parameter.Type == ParameterType.HttpHeader).ToArray(); + + Assert.AreEqual("application/json", requestHeaders.First(parameter => parameter.Name == "Accept").Value); + Assert.AreEqual("en-us,en;q=0.5", requestHeaders.First(parameter => parameter.Name == "Accept-Language").Value); + Assert.AreEqual("300", requestHeaders.First(parameter => parameter.Name == "Keep-Alive").Value); + Assert.AreEqual(3, requestHeaders.Length); + } + + [Test] + public void AddOrUpdateHeaders_ShouldUpdateHeaders_WhenAllExists() + { + // Arrange + var headers = new Dictionary + { + { "Accept", "application/json" }, + { "Keep-Alive", "300" } + }; + var updatedHeaders = new Dictionary + { + { "Accept", "application/xml" }, + { "Keep-Alive", "400" } + }; + + var request = new RestRequest(); + request.AddHeaders(headers); + + // Act + request.AddOrUpdateHeaders(updatedHeaders); + + // Assert + var requestHeaders = request.Parameters.Where(parameter => parameter.Type == ParameterType.HttpHeader).ToArray(); + + Assert.AreEqual("application/xml", requestHeaders.First(parameter => parameter.Name == "Accept").Value); + Assert.AreEqual("400", requestHeaders.First(parameter => parameter.Name == "Keep-Alive").Value); + Assert.AreEqual(2, requestHeaders.Length); + } + + [Test] + public void AddOrUpdateHeaders_ShouldAddAndUpdateHeaders_WhenSomeExists() + { + // Arrange + var headers = new Dictionary + { + { "Accept", "application/json" }, + { "Keep-Alive", "300" } + }; + var updatedHeaders = new Dictionary + { + { "Accept", "application/xml" }, + { "Accept-Language", "en-us,en;q=0.5" } + }; + + var request = new RestRequest(); + request.AddHeaders(headers); + + // Act + request.AddOrUpdateHeaders(updatedHeaders); + + // Assert + var requestHeaders = request.Parameters.Where(parameter => parameter.Type == ParameterType.HttpHeader).ToArray(); + + Assert.AreEqual("application/xml", requestHeaders.First(parameter => parameter.Name == "Accept").Value); + Assert.AreEqual("en-us,en;q=0.5", requestHeaders.First(parameter => parameter.Name == "Accept-Language").Value); + Assert.AreEqual("300", requestHeaders.First(parameter => parameter.Name == "Keep-Alive").Value); + Assert.AreEqual(3, requestHeaders.Length); + } } }