-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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
net/http: add Transport.Clone #26013
Comments
Well, it is safe to do this: package main
import "net/http"
func main() {
defCopy := *(http.DefaultTransport.(*http.Transport))
var tr *http.Transport = &defCopy
_ = tr
} ... but only early in the program before the DefaultTransport has been used. And unfortunately that idiom causes vet failures:
So, yeah, maybe a new function to return a default is warranted, and/or we can fix vet. |
The Copy function from https://play.golang.org/p/cotZaihUxdi does not cause vet to complain, and I'm pretty sure that all the exported fields of go 1.10 Transport are safe to copy. The problem is if this feature can be guarantee in the future. On the other hand, a new function advantage is that it can also setup HTTP 2. |
If code needs to make transports derived from others with changes, then it sounds like we should add a Clone method. The reflect blob in the original report is definitely not something we want to encourage. |
@rsc As to the help wanted tag, I wouldn't be very sure what to start contributing yet as the Clone method; therefore, per NeedsDecision, would you intend further discussion (such as design questions/proposals) taking place here, or in a proposal in the proposals repo? Specifically, I'm still having trouble understanding for Clone:
For the record, and ease of discussion, an alternative proposal that I pondered in the original post on golang-nuts could be something like: package http
var DefaultTransport = NewDefaultTransport()
func NewDefaultTransport() RoundTripper {
return &Transport{
Proxy: ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
} |
I'm moving this from NeedsDecision to NeedsFix. Seems like copying a I'm not sure why I would imagine that a |
@ianlancetaylor Thanks! As to RoundTripper: the http.DefaultTransport is of RoundTripper interface type, that's why I was wondering where the Clone should be defined. (In my original use case, I need to clone the http.DefaultTransport variable.) I suppose adding the method on Transport and accessing it via a cast on DefaultTransport is the only reasonable/acceptable way to go. In the common case it would probably be OK to call it as As to DialContext, I believe I didn't think it through well enough. The comment on DialContext already seems to mention that the func must be safe to run concurrently, so I suppose there shouldn't be any more problems with it. edit: I tried to start writing the Clone, in order to submit a CL, but I'm becoming afraid to do that. Specifically, the comment on unexported field Transport.nextProtoOnce makes me feel uneasy: // nextProtoOnce guards initialization of TLSNextProto and
// h2transport (via onceSetNextProtoDefaults)
nextProtoOnce sync.Once Notably, it seems to have a subtle interaction with initialization of HTTP2 support. IIUC, if Transport.TLSNextProto is initialized to nil (default), it allows for automatic initialization of HTTP2 support in the Transport. However, this results in nextProtoOnce.Do(t.onceSetNextProtoDefaults) being called. This then proceeds to set various unexported and exported fields of the Transport, including .TLSNextProto. This leads to two problems, IIUC:
Or do I misunderstand? @bradfitz ? |
@ianlancetaylor Could you please help find someone to give some guidance on how to proceed with this issue? It's marked as "help-needed", but then since I outlined my concerns as to how should I proceed with implementing it 5 months ago, I got no response, and I believe it's seriously non-trivial/tricky esp. for non-core contributors :/ Also, based on those concerns, would you still think that .Clone() is the way to go here? edit: Please note, that the issue is particularly annoying to us, in that we need to remember to revisit a fragment of code related to it every time we upgrade Go to a newer release... and as you certainly understand, this can be easy to miss, which then can have some subtle, tricky, hard to detect and hard to track consequences for us :/ |
Ping @bradfitz |
@ianlancetaylor Could you please maybe at least remove the NeedsFix tag and mark again with NeedsDecision or something? Maybe the NeedsFix or the help-wanted hides it in Brad's filters or something? :( I don't believe "The path to resolution is known" in this case anymore, per my comment above. |
I'm fine with Clone calling the receiver value's Once.Do func(s). As for TLSNextProto, how about adding a new unexported bool like |
@akavel, any update? You have 1.5 days to get this in to Go 1.13 before the freeze. |
@bradfitz Nope, sorry, no chance. My life & work situation unexpectedly got somewhat dense in the meantime, so I'm not sure if and when I'll be able to proceed with this. |
Change https://golang.org/cl/174597 mentions this issue: |
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (
go version
)?go1.10.3 linux/amd64
Does this issue reproduce with the latest release?
Yes
Describe the issue
In a recent topic on golang-nuts (https://groups.google.com/forum/#!topic/golang-nuts/JmpHoAd76aU) the user reported how hard is to set safe defaults on a custom Transport.
New fields may be added in future releases, and have custom (not zero) default value set for DefaultTransport.
Using a function to copy exported fields (like https://play.golang.org/p/cotZaihUxdi) may cause problems.
I think that the documentation of Transport should document this issue. Is it safe to copy the exported fields of a Transport?
If this cannot be guaranteed, the http package should export a new function, like NewTransportWithDefaults.
The text was updated successfully, but these errors were encountered: