We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
If you ever have the need to combine a plain HTTP webserver with a gRPC server on the same port, then you can use cmux to do so.
You can do something like:
package main
import (
"log"
"net"
"net/http"
"github.com/soheilhy/cmux"
"golang.org/x/sync/errgroup"
"google.golang.org/grpc"
)
func main() {
// Create the listener
l, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatal(err)
}
// Create a new cmux instance
m := cmux.New(l)
// Create a grpc listener first
grpcListener := m.MatchWithWriters(cmux.HTTP2MatchHeaderFieldSendSettings("content-type", "application/grpc"))
// All the rest is assumed to be HTTP
httpListener := m.Match(cmux.Any())
// Create the servers
grpcServer := grpc.NewServer()
httpServer := &http.Server{}
// Use an error group to start all of them
g := errgroup.Group{}
g.Go(func() error {
return grpcServer.Serve(grpcListener)
})
g.Go(func() error {
return httpServer.Serve(httpListener)
})
g.Go(func() error {
return m.Serve()
})
// Wait for them and check for errors
err = g.Wait()
if err != nil {
log.Fatal(err)
}
}
This also demonstrates how the errgroup module can be used. The Wait
method blocks until all function calls from the Go
method have returned, then returns the first non-nil error (if any) from them.
PS: the example itself doesn't actually do something useful as we didn't register any gRPC functions neither did I define HTTP handlers.
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.