-
Notifications
You must be signed in to change notification settings - Fork 18k
x/net/http2: decide what to do about Transport.CancelRequest #13540
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
Could we make CancelRequest do nothing? It is already racy, so it's effectively best effort and we could just drop the effort. That would mean that net/http.Client doesn't have to change except to use the channel. I'm not sure I see why that would imply it has to mutate the request. Or make CancelRequest close the Cancel channel? |
@dsymonds There's nothing stopping people today from writing code that uses both CancelRequest and a Cancel channel. (Not that it makes much sense.) So making CancelRequest close the Cancel channel could cause a double-close, yes? |
Yeah, but we could just tell people not to do that. |
No, that's not really a great option. It does work mostly work today. It's only in some edge cases that it doesn't work.
So you're okay with Client using the channel? That means temporarily mutating & restoring the field on the Request because a Client uses a RoundTripper (e.g. Transport) (or potentially N RoundTripper composed deep) and passes down a Request (which has a Cancel). The Cancel (read: "context") is not a separate argument. |
CL https://golang.org/cl/18260 mentions this issue. |
The net/http.Transport.CancelRequest method is an old feature & wart.
There is no interface which defines it, but it's sniffed for by many RoundTrippers and users of RoundTrippers (including net/http.Client for its Client.Timeout feature), and it's a thorn in the side of people trying to write composable RoundTripper implementations.
The modern replacement is the net/http.Request.Cancel receive-only channel to do cancelations. (closed by caller on cancel)
Unfortunately, net/http.Client doesn't use the Cancel channel. Perhaps it could. But that would require mutating the caller's *Request, at least for Do. But for net/http.Client methods like Get, Head, Post, and PostForm, we create the *http.Request, so we could set the Cancel channel appropriately.
That leaves net/http.Client.Do, which takes a raw *Request. Is it allowed to set the Cancel channel if it's nil? Probably not? Or maybe there is precedent in mutating the Request: we read from the Request.Body, so it's not safe to use concurrently already. So maybe we can just save/restore the Request.Cancel field.
Related to that debate is whether x/net/http2.Transport should have an old-style CancelRequest method. It would really be nice to stop letting that mistake infect things, though, spreading the idea that everybody needs to implement CancelRequest.
But unfortunately as-is, Client Timeouts are failing with http2: https://go-review.googlesource.com/#/c/17528/1 From the second comment:
Thoughts welcome.
/cc @rsc @dsymonds @okdave @mcgreevy @bmizerany
The text was updated successfully, but these errors were encountered: