-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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: Cannot set default 'h2' and other NextProto handler concurrently #16588
Comments
At most we can document this more, but we're not going to change the behavior here. Go 1.6 had the If you want to do something fancy like this, just |
Thanks, I'll take a look at that! I figured this would end up as a documentation issue rather than a code change, unfortunately. Since you know the code well... It appears that modifying the map after I call Serve would do what I want, with the obvious caveat of a race condition on that map. Understanding the risks, from a purely functional standpoint, do you think that would work? Thanks! |
Or you could use a dummy net.Listener which just immediately returns EOF and call I did something like that in https://go-review.googlesource.com/#/c/25280/3/src/net/http/serve_test.go for a unit test. See https://github.com/golang/go/blob/release-branch.go1.7/src/net/http/serve_test.go#L45-L74 |
type dummyListener struct {}
func (dummyListener) Accept() (net.Conn, error) { return nil, io.EOF }
func (dummyListener) Close() error { return nil }
func (dummyListener) Addr() net.Addr { return net.ParseIP("127.0.0.1") }
....
func main() {
var srv http.Server
src.Serve(dummyListener{}) // now h2 is registered
// now set up other protocols |
Hi @bradfitz, That's basically exactly what I was asking about. After the first Serve call, to set up the other protos, you'd add them to the NextProtos map...correct? But since the Server is already handling connections, goroutines spun out by the first listener will read the map while you write the new values to it, introducing a race condition. Am I reading that wrong? |
Serve blocks until the listener is done. Yes, new goroutines are spun up for new connections, but that dummyListener never returns any connection, so things should be quiescent and safe for having its NextProtos mucked with. Of course, you could also just avoid all those hacks and import |
Aha! That's what I was missing. I do plan to avoid the hacks; I hadn't seen that function until you pointed me at it, but it looks great. But it's nice to understand the other bit too -- thanks for explaining! |
Not sure what the plan is for this, if anything. @bradfitz? |
@rsc, it's labeled Documentation, so it's lower priority. Those can be done next week after the freeze. |
CL https://golang.org/cl/33090 mentions this issue. |
Please answer these questions before submitting your issue. Thanks!
go version
)?1.7rc4
go env
)?(Code only)
Took a dive through code trying to work out how to do this.
Here's what I believe the problem to be, although maybe this is purely a documentation bug.
Let's say you want to use the built-in
h2
handling but also define your own handler for your own protocol. According to the documentation:So far so good. But what about if
TLSNextProto
isn't nil? When aServer
starts serving (viaServe()
), according to the method comments:OK, so this appears to indicate that one should specify a
NextProtos
field in the providedtls.Config
includingh2
, which is fine. But now let's dig into the code.In function
setupHTTP2_Serve()
it calls a once object to set up the defaults:Let's look at whether it should configure:
So if we've put
h2
into ourtls.Config.NextProtos
then we return true, meaning we should be configuring HTTP/2 automatically. So now let's look at the defaults function:The problem is the check for
srv.TLSNextProto == nil
. The code here doesn't act according to any of the previous documentation; on the user facing side it doesn't explicitly say that HTTP/2 will be activated in this case but doesn't state that this is a case in which it won't be, unlike other cases. TheshouldConfigureHTTP2ForServe()
check indicates that in fact we should be activating HTTP/2 support because we've explicitly enabled it...but then it isn't.I'm guessing that the reason behind this is that you don't want to clobber a user-set value for
h2
inNextProtos
, but since the built-in function isn't exported, there is no way that I can see to specify a custom protocol and have the connection use Go's built-in HTTP/2 handling.As it stands it seems like my only option as a user is to modify that map after I've called
Serve
and let the defaulth2
handler be propagated into it. This will probably work, but seems like a bad idea and potentially racy since onceServe
is called reads will be performed on the map.My suggestion is that the check for
srv.TLSNextProto == nil
should instead be checking for eithernil
or checking whether the map already contains a value forh2
, and if not, adding the default handling.The text was updated successfully, but these errors were encountered: