feat: use same port for grpc-web and api server (#14652)

This commit is contained in:
Julien Robert
2023-01-20 15:07:17 +00:00
committed by GitHub
parent a4cf8e8c6f
commit 4f6f6c0002
16 changed files with 338 additions and 151 deletions
+36 -12
View File
@@ -12,8 +12,10 @@ import (
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/improbable-eng/grpc-web/go/grpcweb"
"github.com/tendermint/tendermint/libs/log"
tmrpcserver "github.com/tendermint/tendermint/rpc/jsonrpc/server"
"google.golang.org/grpc"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/codec/legacy"
@@ -28,6 +30,8 @@ type Server struct {
GRPCGatewayRouter *runtime.ServeMux
ClientCtx client.Context
GRPCSrv *grpc.Server
logger log.Logger
metrics *telemetry.Metrics
// Start() is blocking and generally called from a separate goroutine.
@@ -52,7 +56,7 @@ func CustomGRPCHeaderMatcher(key string) (string, bool) {
}
}
func New(clientCtx client.Context, logger log.Logger) *Server {
func New(clientCtx client.Context, logger log.Logger, grpcSrv *grpc.Server) *Server {
// The default JSON marshaller used by the gRPC-Gateway is unable to marshal non-nullable non-scalar fields.
// Using the gogo/gateway package with the gRPC-Gateway WithMarshaler option fixes the scalar field marshalling issue.
marshalerOption := &gateway.JSONPb{
@@ -63,9 +67,9 @@ func New(clientCtx client.Context, logger log.Logger) *Server {
}
return &Server{
logger: logger,
Router: mux.NewRouter(),
ClientCtx: clientCtx,
logger: logger,
GRPCGatewayRouter: runtime.NewServeMux(
// Custom marshaler option is required for gogo proto
runtime.WithMarshalerOption(runtime.MIMEWildcard, marshalerOption),
@@ -78,6 +82,7 @@ func New(clientCtx client.Context, logger log.Logger) *Server {
// GRPC metadata
runtime.WithIncomingHeaderMatcher(CustomGRPCHeaderMatcher),
),
GRPCSrv: grpcSrv,
}
}
@@ -100,18 +105,41 @@ func (s *Server) Start(cfg config.Config) error {
return err
}
s.registerGRPCGatewayRoutes()
s.listener = listener
var h http.Handler = s.Router
s.mtx.Unlock()
if cfg.API.EnableUnsafeCORS {
allowAllCORS := handlers.CORS(handlers.AllowedHeaders([]string{"Content-Type"}))
return tmrpcserver.Serve(s.listener, allowAllCORS(h), s.logger, tmCfg)
// configure grpc-web server
if cfg.GRPC.Enable && cfg.GRPCWeb.Enable {
var options []grpcweb.Option
if cfg.API.EnableUnsafeCORS {
options = append(options,
grpcweb.WithOriginFunc(func(origin string) bool {
return true
}),
)
}
wrappedGrpc := grpcweb.WrapServer(s.GRPCSrv, options...)
s.Router.PathPrefix("/").Handler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
if wrappedGrpc.IsGrpcWebRequest(req) {
wrappedGrpc.ServeHTTP(w, req)
return
}
// Fall back to grpc gateway server.
s.GRPCGatewayRouter.ServeHTTP(w, req)
}))
}
// register grpc-gateway routes (after grpc-web server as the first match is used)
s.Router.PathPrefix("/").Handler(s.GRPCGatewayRouter)
s.logger.Info("starting API server...")
if cfg.API.EnableUnsafeCORS {
allowAllCORS := handlers.CORS(handlers.AllowedHeaders([]string{"Content-Type"}))
return tmrpcserver.Serve(s.listener, allowAllCORS(s.Router), s.logger, tmCfg)
}
return tmrpcserver.Serve(s.listener, s.Router, s.logger, tmCfg)
}
@@ -122,10 +150,6 @@ func (s *Server) Close() error {
return s.listener.Close()
}
func (s *Server) registerGRPCGatewayRoutes() {
s.Router.PathPrefix("/").Handler(s.GRPCGatewayRouter)
}
func (s *Server) SetTelemetry(m *telemetry.Metrics) {
s.mtx.Lock()
s.metrics = m