-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: net/http: Add NewDefaultTransport function #39299
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
Comments
how is this different from |
@seankhliao As I mentioned, |
I'm not sure I understand the use case of "I will happily accept whatever defaults the Go project deems appropriate (from NewDefaultTransport) but reject any defaults decided by the author of the running program and its specific environment". Why is one set of defaults fine and not the other? |
@eandre I'm not sure what you mean by "the author of the running program". Any external library can just modify the global variable. So the issues are:
In my opinion, the |
I don't have strong feelings for or against your proposal, but you seem to be taking an adversarial stance against these dependencies ("who knows what they might do?"). My point of view is that as an author of a binary, you are responsible for what libraries you pull in and what they do. Rather than viewing any change to the Ignoring these settings is only "correct" in a sense if you take the stance that any changes to |
@eandre I am confused by your argument. You say both "as an author of a binary, you are responsible for what libraries you pull in and what they do" and "the author of the binary should know what they're doing, and if they are using code that reconfigures the default transport, I should follow along with their wishes." Those sound like mutually exclusive scenarios to me. If I am authoring a binary, then I should have control over the creation of the transport. If I have requirements concerning the timing of the network operations, then I should be creating a transport with such settings. But I don't see a reason I would want to clone the default transport (as in the global) to do so. At best, it would be the same thing as constructing a new default transport, and at worst it could actually cause an unintentional issue. However, I could see why somebody would want to modify/replace the global variable itself in their top-level code. If I am authoring a library, then I should allow the client to pass in an My concrete use case is we needed to disable HTTP/2 on the transport, but wanted to leverage the rest of the default settings. Consequently, we ended up with something like:
This did not actually work as expected due to #39302. However, even if it did, the fact that that requires a typecast, and there is no way to handle the typecast failing without just aborting the binary, is disconcerting. Additionally, we do not like the implication that we are forced to accept any changes to the global that could have been made elsewhere. (This is also a concern with just using the default transport global variable normally, but it became more apparent here.) If someone really wants those changes, they are free to use the |
It would be helpful if you could cite a real-world example that drove this proposal. Was there a case where a third-party library modified some values of the DefaultTransport or swapped it with something else without documenting it ? The same argument could be theoretically made for any global variable in the standard library. IIUC, this is primarily about not having to copy the default timeouts to the codebase separately to create a separate transport. Would that be accurate ? |
Thankfully, this has not yet happened with the libraries that we have used. But the issues I see are (1) this leads to fragile code that fundamentally relies on nothing else in the entire binary (including some transitive dependency of a dependency) changing that global; and (2) it prevents us from writing properly robust code due to the following no-win situation. t, ok := http.DefaultTransport.(*http.Transport)
if !ok {
// now what?
}
t2 := t.Clone()
...
Indeed, which is partially why, in my opinion, properly robust code should never be using global variables.
Yes, especially because we would have to manually maintain those default settings with each new Go release. As I mentioned above, if the zero value for Also, one thing I would like some clarification on is what specifically instigated the introduction of the |
We would like to be able to use the default options for
http.Transport
without modifying the global, or worrying about whether anyone has modified the transport, or having to typecast it to callClone
. I propose adding aNewDefaultTransport() *Transport
function to the http package. It should return a newTransport
with the default options filled out. The global definition then becomesvar DefaultTransport RoundTripper = NewDefaultTransport()
. Note that the function returns*Transport
notRoundTripper
so we don't have to typecast it.This was previously discussed in #26013, but in that case people wanted to pull in modifications to the global that had been made, so the
Clone()
method was introduced.The text was updated successfully, but these errors were encountered: