gateway.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. package gateway
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "fmt"
  6. "io"
  7. "io/fs"
  8. "mime"
  9. "net/http"
  10. "os"
  11. "strings"
  12. "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
  13. "github.com/osguydch/ccosproc/insecure"
  14. "github.com/osguydch/ccosproc/middleware"
  15. usersv1 "github.com/osguydch/ccosproc/proto/device/v3"
  16. "github.com/osguydch/ccosproc/third_party"
  17. "google.golang.org/grpc"
  18. "google.golang.org/grpc/credentials"
  19. "google.golang.org/grpc/grpclog"
  20. )
  21. // getOpenAPIHandler serves an OpenAPI UI.
  22. // Adapted from https://github.com/philips/grpc-gateway-example/blob/a269bcb5931ca92be0ceae6130ac27ae89582ecc/cmd/serve.go#L63
  23. func getOpenAPIHandler() http.Handler {
  24. mime.AddExtensionType(".svg", "image/svg+xml")
  25. // Use subdirectory in embedded files
  26. subFS, err := fs.Sub(third_party.OpenAPI, "OpenAPI")
  27. if err != nil {
  28. panic("couldn't create sub filesystem: " + err.Error())
  29. }
  30. return http.FileServer(http.FS(subFS))
  31. }
  32. // Run runs the gRPC-Gateway, dialling the provided address.
  33. func Run(dialAddr string, httpPort string, supprtSSL string) error {
  34. // Adds gRPC internal logs. This is quite verbose, so adjust as desired!
  35. log := grpclog.NewLoggerV2(os.Stdout, io.Discard, io.Discard)
  36. grpclog.SetLoggerV2(log)
  37. // Create a client connection to the gRPC Server we just started.
  38. // This is where the gRPC-Gateway proxies the requests.
  39. conn, err := grpc.DialContext(
  40. context.Background(),
  41. dialAddr,
  42. grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(insecure.CertPool, "")),
  43. //grpc.WithInsecure(),
  44. grpc.WithBlock(),
  45. )
  46. if err != nil {
  47. return fmt.Errorf("failed to dial server: %w", err)
  48. }
  49. gwmux := runtime.NewServeMux()
  50. err = usersv1.RegisterDeviceHandler(context.Background(), gwmux, conn)
  51. if err != nil {
  52. return fmt.Errorf("failed to register gateway: %w", err)
  53. }
  54. // 预先创建CORS包装的handlers,避免每次请求重复创建
  55. apiHandler := middleware.Cors(gwmux)
  56. moduleHandler := middleware.Cors(http.StripPrefix("/module/", http.FileServer(http.Dir("./DriverDefine"))))
  57. dataHandler := middleware.Cors(http.StripPrefix("/Data/", http.FileServer(http.Dir("./RawData"))))
  58. openAPIHandler := getOpenAPIHandler()
  59. gatewayAddr := "0.0.0.0:" + httpPort
  60. gwServer := &http.Server{
  61. Addr: gatewayAddr,
  62. Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  63. if strings.HasPrefix(r.URL.Path, "/api") {
  64. log.Info("Serving device apis", r.URL.Path)
  65. apiHandler.ServeHTTP(w, r)
  66. return
  67. }
  68. if strings.HasPrefix(r.URL.Path, "/module") {
  69. log.Info("Serving module definition", r.URL.Path)
  70. moduleHandler.ServeHTTP(w, r)
  71. return
  72. }
  73. if strings.HasPrefix(r.URL.Path, "/Data") {
  74. log.Info("Serving data file", r.URL.Path)
  75. dataHandler.ServeHTTP(w, r)
  76. return
  77. }
  78. openAPIHandler.ServeHTTP(w, r)
  79. }),
  80. }
  81. if supprtSSL != "ON" {
  82. log.Info("Serving gRPC-Gateway and OpenAPI Documentation on http://", gatewayAddr)
  83. return fmt.Errorf("serving gRPC-Gateway server: %w", gwServer.ListenAndServe())
  84. }
  85. gwServer.TLSConfig = &tls.Config{
  86. Certificates: []tls.Certificate{insecure.Cert},
  87. }
  88. log.Info("Serving gRPC-Gateway and OpenAPI Documentation on https://", gatewayAddr)
  89. return fmt.Errorf("serving gRPC-Gateway server: %w", gwServer.ListenAndServeTLS("", ""))
  90. }