package main import ( fmt "fmt" "log" "net/http" "strings" "time" "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/credentials" ) var port = ":5000" type myGrpcServer struct{} func (s *myGrpcServer) SayHello(ctx context.Context, in *HelloRequest) (*HelloReply, error) { return &HelloReply{Message: "Hello " + in.Name}, nil } func main() { go startServer() time.Sleep(time.Second) doClientWork() } func startServer() { creds, err := credentials.NewServerTLSFromFile("tls-config/server.crt", "tls-config/server.key") if err != nil { log.Fatal(err) } grpcServer := grpc.NewServer(grpc.Creds(creds)) RegisterGreeterServer(grpcServer, new(myGrpcServer)) mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { fmt.Fprintln(w, "hello") }) http.ListenAndServeTLS(port, "tls-config/server.crt", "tls-config/server.key", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // TODO(tamird): point to merged gRPC code rather than a PR. // This is a partial recreation of gRPC's internal checks // https://github.com/grpc/grpc-go/pull/514/files#diff-95e9a25b738459a2d3030e1e6fa2a718R61 if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") { grpcServer.ServeHTTP(w, r) } else { mux.ServeHTTP(w, r) } })) } func doClientWork() { creds, err := credentials.NewClientTLSFromFile("tls-config/server.crt", "server.grpc.io") if err != nil { log.Fatal(err) } conn, err := grpc.Dial("localhost"+port, grpc.WithTransportCredentials(creds)) if err != nil { log.Fatal(err) } defer conn.Close() c := NewGreeterClient(conn) r, err := c.SayHello(context.Background(), &HelloRequest{Name: "gopher"}) if err != nil { log.Fatalf("could not greet: %v", err) } log.Printf("doClientWork: %s", r.Message) }