-
Notifications
You must be signed in to change notification settings - Fork 496
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make HTTP components configurable #605
Conversation
was probably testing too much detail here.
Codecov Report
@@ Coverage Diff @@
## master #605 +/- ##
==========================================
+ Coverage 23.21% 23.71% +0.49%
==========================================
Files 85 85
Lines 8672 8717 +45
Branches 719 721 +2
==========================================
+ Hits 2013 2067 +54
+ Misses 6528 6517 -11
- Partials 131 133 +2
Continue to review full report at Codecov.
|
Some things that I feel like should be considered, both WebAPI and CDNClient expose timeouts differently, and I think it could be handled with this. SteamKit/SteamKit2/SteamKit2/Steam/WebAPI/WebAPI.cs Lines 179 to 182 in 4360d6f
And why does CDNClient use cancellation token instead of httpclient's timeout properties? |
I think CDNClient uses a cancellation token because it's a direct translation of the old code which used I'd be happy to make CDNClient use HttpClient.Timeout instead, but as a separate refactor. |
{ | ||
var client = config.GetHttpClient(); | ||
|
||
client.BaseAddress = config.WebAPIBaseAddress; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't this cause issues if consumer is using HttpClient for his own requests with custom base address (or lack of it)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The consumer shouldn’t be doing that. They can share an underlying HttpMessageHandler, but shouldn’t be sharing the HttpClient itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably good idea to mention it then, I'd expect from SK2 to use my HttpClient as it is, without modifying its properties such as the base address.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would agree here, It should be easy enough to just pass base address into urlBuilder
directly instead of using HttpClient.BaseAddress
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The xmldoc calls this out by differentiating between “returns a new or existing XXXXX” and “creates a new XXXXX”.
Sharing an http client outside of our own library would drastically limit how much of its functionality we can actually use, both now and into the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a fair point, if you can see how it'd bite us in the future then I see no need to do any of that. In fact, I'd even vouch for complete removal of custom HttpClient
and leave handler only, but sadly there are HttpClient
settings that the consumer might want to supply, mainly default request headers for identification purposes.
Maybe it could be a good idea to allow consumer to supply only its own HttpClientHandler
and default headers, leaving creating HttpClient
to SK2. I don't see any other reason for one to force usage of its own HttpClient
, and because SK2 is expected to modify its properties anyway, doing it this way would avoid a lot of confusion (even if it's stated in the doc).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the consumer wants to re-use HttpMessageHandler
instances, then the HttpClient
has to be created with dispose: false
so that the handler is re-usable and not killed early.
We could make a bool ShouldDisposeOfHandler(HttpMessageHandler handler)
method, but that seems oddly specific.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels fine for me to supply message handler, default headers and value specifying that my handler is supposed to be reused in my own routines further, so it shouldn't be disposed.
Considering that there is really not much more to add towards that (I mean, you've defined everything regarding how to create and use HttpClient
by now), I feel that it's a good tradeoff for having a guarantee that HttpClient
created by SK2 has expected state and no issues as long as user can guarantee that his message handler is proper.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still, this is more like a design choice over personal preferences rather than some crucial decision, so I leave that up to you, the PR is fine as it is, I just don't see a reason why consumer must create HttpClient
and ensure it meets all SK2 requirements and can be modified, if SK2 can pretty much do the same with just 1 more argument (headers + disposing vs httpclient alone).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the consumer:
- Doesn't supply their own message handler factory
- Supplies a new message handler each time
Then they don't need to create a HttpClient
. If they want more advanced control, then I'd rather give them more advanced control rather than re-invent the wheel.
For example, they could use HttpClientFactory
with few (if any) modifications.
I'm starting to question whether or not we need |
Sounds good to me and this is what I suggested back then. If you're expecting I thought about hypothetical situation in which SK2 would want to do something with handler before creating So yes, if you can't find any edge case, I think it's a good idea. |
Hmmm. I did some more thinking and, in theory, we could possibly maybe some day want to insert our own However, what we could do then, is:
It's two more object allocations, but if that be comes a problem then we can optimize later down the road some day. No point whatsoever doing that prematurely. So yeah, it looks like we only need the one of these extensibility points. I'll refactor. |
Any last thoughts or comments? |
Users can provide one or two new factory functions to
SteamConfiguration
:HttpMessageHandler
factory function, which is the inner part of the pipeline that actually executes HTTP requests, andHttpClient
factory function, which is a nice wrapper class that the rest of the .NET HTTP stack is built around.Users can use these two injection points to, for example:
Note that this only affects WebAPI, it has no bearing on Websocket CM connections. We could expose
ClientWebSocketOptions
some day, but that's another PR for another issue, if/when it's ever needed.This resolves #450 and #541.
For now I've simply attached them to
SteamConfiguration
, but as the configuration gets bigger we might want to split it up - for example, these two factory methods could be put on an interface, we provide a default implementation, andSteamConfiguration
would only have one HTTP-related method/property to get/replace the HTTP configuration object.