Skip to content

Instantly share code, notes, and snippets.

@jamisonhyatt
Last active April 21, 2017 19:16
Show Gist options
  • Save jamisonhyatt/3a6f8533f8c1b50691c8beff8ec47355 to your computer and use it in GitHub Desktop.
Save jamisonhyatt/3a6f8533f8c1b50691c8beff8ec47355 to your computer and use it in GitHub Desktop.
grpc http mux
package main
var TLS = true
var port = 443
var certificateFile = "./server_localhost.pem"
var keyFile = "./server_localhost.pkcs8key"
func main() {
SetupMuxedServer().Serve()
}
func SetupMuxedServer() ( *mux.MuxServer) {
var err error
var listener net.Listener
if TLS {
cert, err := tls.LoadX509KeyPair(certificateFile, keyFile)
if err != nil {
panic(err)
}
config := &tls.Config{Certificates: []tls.Certificate{cert}}
listener, err = tls.Listen("tcp", fmt.Sprintf(":%d", port), config)
} else {
listener, err = net.Listen("tcp", fmt.Sprintf(":%d", port))
}
if err != nil {
panic(err)
}
muxedServer := mux.NewMuxServer(listener)
muxedServer.SetGrpcServer(SetupGRPCServer())
muxedServer.SetHttpServer(SetupHttpServer())
return muxedServer
}
func setupGRPCServer() ( *grpc.Server) {
var opts []grpc.ServerOption
//add opts....
server := grpc.NewServer(opts...)
grpcHealth := health.NewServer()
example_proto.RegisterExampleServer(grpcServer, &example.exampleImplementation{})
grpc_health_v1.RegisterHealthServer(server, grpcHealth)
return server
}
func setupHttpServer() *http.Server {
h := http.NewServeMux()
h.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%s\n", "ok")
})
httpServer := &http.Server{
Handler: h,
}
return httpServer
}
//inspired by https://github.com/gdm85/grpc-go-multiplex
import (
"net"
"net/http"
"google.golang.org/grpc"
"github.com/cockroachdb/cmux"
"log"
)
type MuxServer struct {
mux cmux.CMux
grpcServer *grpc.Server
grpcListener net.Listener
httpServer *http.Server
httpListener net.Listener
}
func NewMuxServer(listener net.Listener) *MuxServer {
mx := MuxServer{mux: cmux.New(listener)}
mx.grpcListener = mx.mux.Match(cmux.HTTP2HeaderField("content-type", "application/grpc"))
mx.httpListener = mx.mux.Match(cmux.Any())
return &mx
}
func (ms *MuxServer) SetHttpServer(srv *http.Server) {
ms.httpServer = srv
}
func (ms *MuxServer) SetGrpcServer(srv *grpc.Server) {
ms.grpcServer = srv
}
func (ms *MuxServer) serveGrpc() error {
return ms.grpcServer.Serve(ms.grpcListener)
}
func (ms *MuxServer) serveHTTP() error {
return ms.httpServer.Serve(ms.httpListener)
}
func (ms *MuxServer) Serve() error {
serveErrors := make(chan error, 2)
go func() { serveErrors <- ms.serveGrpc()}()
go func() { serveErrors <- ms.serveHTTP()}()
muxError := ms.mux.Serve()
if muxError != nil {
log.Printf("mux serve error %v \n", muxError)
}
var serveError error
var i int
for err := range serveErrors {
if err != nil {
log.Printf("protocol serve error: %v\n", err)
serveError = err
}
i++
if i == cap(serveErrors) {
close(serveErrors)
break
}
}
return serveError
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment