github.com/gofunct/common@v0.0.0-20190131174352-fd058c7fbf22/pkg/transport/engine/gateway.go (about)

     1  package engine
     2  
     3  import (
     4  	"context"
     5  	"github.com/gofunct/common/pkg/transport/api"
     6  	"github.com/gofunct/common/pkg/transport/config"
     7  	"net"
     8  	"net/http"
     9  	"time"
    10  
    11  	"github.com/grpc-ecosystem/grpc-gateway/runtime"
    12  	"github.com/pkg/errors"
    13  	"google.golang.org/grpc"
    14  	"google.golang.org/grpc/grpclog"
    15  )
    16  
    17  // NewGatewayServer creates GrpcServer instance.
    18  func NewGatewayServer(c *config.Config) api.Interface {
    19  	return &GatewayServer{
    20  		Config: c,
    21  	}
    22  }
    23  
    24  // GatewayServer wraps gRPC gateway server setup process.
    25  type GatewayServer struct {
    26  	server *http.Server
    27  	*config.Config
    28  }
    29  
    30  // Serve implements Server.Shutdown
    31  func (s *GatewayServer) Serve(l net.Listener) error {
    32  	conn, err := s.createConn()
    33  	if err != nil {
    34  		return errors.Wrap(err, "failed to create connection with grpc-gateway server")
    35  	}
    36  	defer conn.Close()
    37  
    38  	s.server, err = s.createServer(conn)
    39  	if err != nil {
    40  		return errors.Wrap(err, "failed to create gRPC Gateway server: %v")
    41  	}
    42  
    43  	grpclog.Infof("grpc-gateway server is starting %s", l.Addr())
    44  
    45  	err = s.server.Serve(l)
    46  
    47  	grpclog.Infof("stopped taking more http(s) requests: %v", err)
    48  
    49  	if err != http.ErrServerClosed {
    50  		return errors.Wrap(err, "failed to serve grpc-gateway server")
    51  	}
    52  
    53  	return nil
    54  }
    55  
    56  // Shutdown implements Server.Shutdown
    57  func (s *GatewayServer) Shutdown() {
    58  	ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
    59  	defer cancel()
    60  	err := s.server.Shutdown(ctx)
    61  	grpclog.Info("All http(s) requets finished")
    62  	if err != nil {
    63  		grpclog.Errorf("failed to shutdown grpc-gateway server: %v", err)
    64  	}
    65  }
    66  
    67  func (s *GatewayServer) createConn() (conn *grpc.ClientConn, err error) {
    68  	conn, err = grpc.Dial(s.GrpcInternalAddr.Addr, s.ClientOptions()...)
    69  	if err != nil {
    70  		err = errors.Wrap(err, "failed to connect to gRPC server")
    71  	}
    72  	return
    73  }
    74  
    75  func (s *GatewayServer) createServer(conn *grpc.ClientConn) (*http.Server, error) {
    76  	mux := runtime.NewServeMux(
    77  		append(
    78  			[]runtime.ServeMuxOption{runtime.WithProtoErrorHandler(runtime.DefaultHTTPProtoErrorHandler)},
    79  			s.GatewayMuxOptions...,
    80  		)...,
    81  	)
    82  	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
    83  	defer cancel()
    84  
    85  	for _, svr := range s.Servers {
    86  		err := svr.RegisterWithHandler(ctx, mux, conn)
    87  		if err != nil {
    88  			return nil, errors.Wrap(err, "failed to register handler")
    89  		}
    90  	}
    91  
    92  	var handler http.Handler = mux
    93  
    94  	for i := len(s.GatewayServerMiddlewares) - 1; i >= 0; i-- {
    95  		handler = (s.GatewayServerMiddlewares[i])(handler)
    96  	}
    97  
    98  	svr := &http.Server{
    99  		Handler: handler,
   100  	}
   101  	if cfg := s.GatewayServerConfig; cfg != nil {
   102  		cfg.ApplyTo(svr)
   103  	}
   104  
   105  	return svr, nil
   106  }