-
Notifications
You must be signed in to change notification settings - Fork 0
Benefits
This package is designed to deliver some benefits to the developer and application maintainers. It's not just another HTTP client. See the benefits below.
The .NET HttpClient is supposed to be reused across your code, that's why it provides a BaseAddress
, a default Timeout
, a DefaultRequestHeaders
, etc. Creating a new connection is an expensive process. Still most people use it incorrectly, with using
block that triggers a Dispose() at the end. That may be responsible for socket exhaustion in your production server.
This package makes the .NET HttpClient static and private, so you can't touch it.
When making HttpClient static it's very likely it will not close active connections on constant load servers. By constant load I mean that at least once in a minute there's a request arriving in you app. The idle timeout is usually greater than that, what makes that time short enough to consider as active a previously established connection.
You may be asking: What's the problem with that?
The problem is that if the connection is never closed, DNS changes are not honoured. If a service you're consuming changes its IP address, you are not told about that. It's "your" job to lookup the new IP address.
If the IP address changes and the old one is no longer accessible, the connection will be broken. That will be the chance for a new DNS lookup by the .NET HttpClient when trying to establish a new connection. It may still run with an entry cached by the the ServicePointManager or by the operating system, in this order.
In order to solve this, we changed the default connection lease timeout of HttpClient. That forces a connection to close after some time. No requests are lost, it's ok. The original configuration is to never close an active connection (infinite timeout).
Because it makes sense. But, you can register as you want and it will work as expected. Any instance will use the same HttpClient.
One could want to call Dispose() on HttpService to "force" the release of resources as soon as possible. If HttpClient was disposed, a subsequent use of the class would throw an exception. IDisposable
was not implemented on purpose in order to discourage its use.
However, the major motivation to this is when class lifecycle is managed by a DI container and set to scoped. In this case, the Dispose()
would be called implicitly by some DI frameworks, that would lead to this undesired behavior and would go against the purpose of this package.
This could be a static class as there's no need to have a contract. However many mock frameworks don't allow you to mock a static class or a static method.
That's why we provide you an interface. Now you can unit test your service agents.