github.com/resonatecoop/user-api@v1.0.0-13.0.20220915120639-05dc9c04014a/gateway/gateway.go (about) 1 package gateway 2 3 import ( 4 "context" 5 "crypto/tls" 6 "fmt" 7 "io/ioutil" 8 "mime" 9 "net/http" 10 "os" 11 "strings" 12 13 "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 14 "github.com/rakyll/statik/fs" 15 "google.golang.org/grpc" 16 "google.golang.org/grpc/credentials" 17 "google.golang.org/grpc/grpclog" 18 19 "github.com/resonatecoop/user-api/insecure" 20 pbUser "github.com/resonatecoop/user-api/proto/user" 21 22 // Static files 23 _ "github.com/resonatecoop/user-api/statik" 24 ) 25 26 // getOpenAPIHandler serves an OpenAPI UI. 27 // Adapted from https://github.com/philips/grpc-gateway-example/blob/a269bcb5931ca92be0ceae6130ac27ae89582ecc/cmd/serve.go#L63 28 func getOpenAPIHandler() http.Handler { 29 mime.AddExtensionType(".svg", "image/svg+xml") 30 31 statikFS, err := fs.New() 32 if err != nil { 33 // Panic since this is a permanent error. 34 panic("creating OpenAPI filesystem: " + err.Error()) 35 } 36 37 return http.FileServer(statikFS) 38 } 39 40 // Run runs the gRPC-Gateway, dialling the provided address. 41 func Run(dialAddr string) error { 42 // Adds gRPC internal logs. This is quite verbose, so adjust as desired! 43 log := grpclog.NewLoggerV2(os.Stdout, ioutil.Discard, ioutil.Discard) 44 grpclog.SetLoggerV2(log) 45 46 // Create a client connection to the gRPC Server we just started. 47 // This is where the gRPC-Gateway proxies the requests. 48 conn, err := grpc.DialContext( 49 context.Background(), 50 dialAddr, 51 grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(insecure.CertPool, "")), 52 grpc.WithBlock(), 53 ) 54 if err != nil { 55 return fmt.Errorf("failed to dial server: %w", err) 56 } 57 58 gwmux := runtime.NewServeMux() 59 err = pbUser.RegisterResonateUserHandler(context.Background(), gwmux, conn) 60 61 if err != nil { 62 return fmt.Errorf("failed to register gateway: %w", err) 63 } 64 65 oa := getOpenAPIHandler() 66 67 port := os.Getenv("PORT") 68 if port == "" { 69 port = "11000" 70 } 71 gatewayAddr := "0.0.0.0:" + port 72 gwServer := &http.Server{ 73 Addr: gatewayAddr, 74 Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 75 if strings.HasPrefix(r.URL.Path, "/api") { 76 gwmux.ServeHTTP(w, r) 77 return 78 } 79 oa.ServeHTTP(w, r) 80 }), 81 } 82 // Empty parameters mean use the TLS Config specified with the server. 83 if strings.ToLower(os.Getenv("SERVE_HTTP")) == "true" { 84 log.Info("Serving gRPC-Gateway and OpenAPI Documentation on http://", gatewayAddr) 85 return fmt.Errorf("serving gRPC-Gateway server: %w", gwServer.ListenAndServe()) 86 } 87 88 gwServer.TLSConfig = &tls.Config{ 89 Certificates: []tls.Certificate{insecure.Cert}, 90 } 91 log.Info("Serving gRPC-Gateway and OpenAPI Documentation on https://", gatewayAddr) 92 return fmt.Errorf("serving gRPC-Gateway server: %w", gwServer.ListenAndServeTLS("", "")) 93 }