I am trying to avoid to create a new HttpClient on each request (see #144) because this application is doing a lot of requests and for long time.
But, headers configuration seems to be associated to HttpClient instance in place of FlurlClient instance, so when I try to set If-None-Match header, it is added to the previous ones in place of replace them as you can see in the follow example:
```c#
var flurlClient = new FlurlClient();
var _lastEtag1 = "769923b";
var _lastEtag2 = "da030d2";
var data1 = await flurlClient
.WithUrl("htp://www.host.com/resource1.json")
.WithHeader("If-None-Match", _lastEtag1)
.GetAsync();
// GET http://www.host.com/resource1.json HTTP/1.1
// If-None-Match: "769923b"
// Host: www.host.com
var data2 = await flurlClient
.WithUrl("htp://www.host.com/resource2.json")
.WithHeader("If-None-Match", _lastEtag2)
.GetAsync();
// GET http://www.host.com/resource2.json HTTP/1.1
// If-None-Match: "769923b", "da030d2" <-----------
// Host: www.host.com
```
I think that the issue is in ClientConfigExtensions where WithHeader() is touching HttpClient in place of keep the headers to be applied to the request.
Thanks for you library, it is really nice and usable!
I also tried with Clone(), but it neither works.
You are correct that WithHeader sets the header on the client and is subsequently passed with each request. Often that's desired but I can see how it doesn't work here. The quick fix is to do this between calls:
flurlClient.HttpClient.DefaultRequestHeaders.Clear();
Maybe a fluent ClearHeaders() shortcut method would be a better long-term solution?
Mmmm, I think that it is not a good solution because it could generate issues in multi thread scenarios.
Yes, good point. There's not a very good work-around for this so I'll get it on the 2.0 roadmap to come up with a fix.
Hi @tmenier , @andresmoschini
I was having the same problem and I think a solution could be to expose a method in FlurlClient that accepts an HttpRequestMessage.
Doing this you can use:
Flurl is already creating an HttpRequestMessage internally, but if we have this method exposed we can go on a full 100% thread safety approach using only one instance of HttpClient.
Then we can use for example:
c#
flurlClient.SendAsync(httpRequestMessage, cancellationToken)
As this is also a supported signature for the HttpClient.
Regards,
@pmorelli92 I agree that something along those lines is probably appropriate. I've always said I'd rather provide hooks to get at the underlying HttpClient mechanisms than try to abstract away everything, but there's currently no hook to get at HttpRequestMessage. I'll do some thinking on how to do that in a way that's the most natural fit for the library.
I really need this too. I've got a couple of ideas and will try to find the time to put a PR together.
@pmorelli92 @gitfool I should have updated this issue a while back. Flurl.Http has SendAsync (and PostAsync, etc) that take HttpContent objects as of 1.0. You give up some fluent prettiness so there still might be a potential enhancement here, but it's one way to set per-request headers for now.
Yeah I saw that, but that approach gives up what I love most about Flurl. Thinking...
Flurl.Http 2.0 will include first-class support of request-level headers.
What ever happened to this? We're seeing no difference with the behavior originally described in this bug -- all headers appear to apply to all requests. There seems to be no documentation on request-level headers, at least not that I can find. Am I just missing something?
@htxryan You might need to post some code. This is a very old issue and the original posted code won't even compile because WithUrl was removed in 2.0. If you call WithHeader on a FlurlClient, it'll apply to all requests made with that client. If you call it on anything else (FlurlRquest, Url, string) it'll apply it to the request.