soheilhy / cmux

Connection multiplexer for GoLang: serve different services on the same port!
Apache License 2.0
2.53k stars 197 forks source link

Doesn't work with grpc-go's hello world example #82

Closed MakotoE closed 3 years ago

MakotoE commented 3 years ago

If I change https://github.com/grpc/grpc-go/blob/81b95b1854d7caf3cc21aed316fc222e1749cf31/examples/helloworld/greeter_server/main.go#L53 to:

m := cmux.New(lis)
go func() {
    if err := s.Serve(m.Match(cmux.Any())); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}()
m.Serve()

This works as expected. The client side prints 2020/12/12 09:37:44 Greeting: Hello world. But if I add the content-type matcher,

m := cmux.New(lis)
go func() {
    if err := s.Serve(m.Match(cmux.HTTP2HeaderField("content-type", "application/grpc"))); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}()
m.Serve()

The client cannot connect and blocks forever. In this switch https://github.com/soheilhy/cmux/blob/8a8ea3c53959009183d7914522833c1ed8835020/matchers.go#L241 I see that the case *http2.SettingsFrame: is being taken but not case *http2.ContinuationFrame: or case *http2.HeadersFrame: and I am guessing either of those two branches are supposed to be taken. Unit tests in this repo are passing. I'm not sure what is wrong.

MakotoE commented 3 years ago

I just got it to work using HTTP2MatchHeaderFieldSendSettings. I'm not sure why this work while the previous method didn't.

m := cmux.New(lis)
go func() {
    if err := s.Serve(m.MatchWithWriters(cmux.HTTP2MatchHeaderFieldSendSettings("content-type", "application/grpc"))); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}()
m.Serve()
zepatrik commented 3 years ago

I had the same problem. I always got a Method: PRI ... request that the server could not handle. Maybe something in the go-grpc client changed recently? Anyway, using cmux.HTTP2MatchHeaderFieldSendSettings works.