diff --git a/Refit-Tests/RequestBuilder.cs b/Refit-Tests/RequestBuilder.cs index af4d06730..3da09b2dc 100644 --- a/Refit-Tests/RequestBuilder.cs +++ b/Refit-Tests/RequestBuilder.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Net.Http; using System.Collections.Generic; using System.Linq; @@ -228,6 +229,12 @@ public interface IDummyHttpApi Task FetchSomeStuffWithVoid(); string SomeOtherMethod(); + + [Put("/foo/bar/{id}")] + Task PutSomeContentWithAuthorization(int id, [Body] object content, [Header("Authorization")] string authorization); + + [Put("/foo/bar/{id}")] + Task PutSomeStuffWithDynamicContentType(int id, [Body] string content, [Header("Content-Type")] string contentType); } public class TestHttpMessageHandler : HttpMessageHandler @@ -423,5 +430,28 @@ public void HttpClientShouldNotPrefixEmptyAbsolutePathToTheRequestUri() Assert.AreEqual("http://api/foo/bar/42", testHttpMessageHandler.RequestMessage.RequestUri.ToString()); } + + [Test] + public void DontBlowUpWithDynamicAuthorizationHeaderAndContent() + { + var fixture = new RequestBuilderImplementation(typeof(IDummyHttpApi)); + var factory = fixture.BuildRequestFactoryForMethod("PutSomeContentWithAuthorization"); + var output = factory(new object[] { 7, new { Octocat = "Dunetocat" }, "Basic RnVjayB5ZWFoOmhlYWRlcnMh" }); + + Assert.IsNotNull(output.Headers.Authorization, "Headers include Authorization header"); + Assert.AreEqual("RnVjayB5ZWFoOmhlYWRlcnMh", output.Headers.Authorization.Parameter); + } + + [Test] + public void SuchFlexibleContentTypeWow() + { + var fixture = new RequestBuilderImplementation(typeof(IDummyHttpApi)); + var factory = fixture.BuildRequestFactoryForMethod("PutSomeStuffWithDynamicContentType"); + var output = factory(new object[] { 7, "such \"refit\" is \"amaze\" wow", "text/dson" }); + + Assert.IsNotNull(output.Content, "Request has content"); + Assert.IsNotNull(output.Content.Headers.ContentType, "Headers include Content-Type header"); + Assert.AreEqual("text/dson", output.Content.Headers.ContentType.MediaType, "Content-Type header has the expected value"); + } } } \ No newline at end of file diff --git a/Refit/RequestBuilderImplementation.cs b/Refit/RequestBuilderImplementation.cs index ebc294473..23cd46a13 100644 --- a/Refit/RequestBuilderImplementation.cs +++ b/Refit/RequestBuilderImplementation.cs @@ -122,10 +122,14 @@ public Func BuildRequestFactoryForMethod(string me void setHeader(HttpRequestMessage request, string name, object value) { // Clear any existing version of this header we may have set, because - // we want to allow removal/redefinition of headers. - request.Headers.Remove(name); + // we want to allow removal/redefinition of headers. - if (request.Content != null) { + // NB: We have to enumerate the header names to check existence because + // Contains throws if it's the wrong header type for the collection. + if (request.Headers.Any(x => x.Key == name)) { + request.Headers.Remove(name); + } + if (request.Content != null && request.Content.Headers.Any(x => x.Key == name)) { request.Content.Headers.Remove(name); }