github.com/kaydxh/golang@v0.0.131/pkg/grpc-gateway/grpc_gateway.go (about) 1 /* 2 *Copyright (c) 2022, kaydxh 3 * 4 *Permission is hereby granted, free of charge, to any person obtaining a copy 5 *of this software and associated documentation files (the "Software"), to deal 6 *in the Software without restriction, including without limitation the rights 7 *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 *copies of the Software, and to permit persons to whom the Software is 9 *furnished to do so, subject to the following conditions: 10 * 11 *The above copyright notice and this permission notice shall be included in all 12 *copies or substantial portions of the Software. 13 * 14 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 *SOFTWARE. 21 */ 22 package grpcgateway 23 24 import ( 25 "context" 26 "net/http" 27 "sync" 28 29 "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 30 grpc_ "github.com/kaydxh/golang/go/net/grpc" 31 http_ "github.com/kaydxh/golang/go/net/http" 32 33 "google.golang.org/grpc" 34 ) 35 36 type InterceptorOption struct { 37 grpcServerOpts struct { 38 unaryInterceptors []grpc.UnaryServerInterceptor 39 streamInterceptors []grpc.StreamServerInterceptor 40 } 41 httpServerOpts struct { 42 handlerChain http_.HandlerChain 43 /* 44 //invoke before http handler 45 PreHttpInterceptors []http_.HandlerInterceptor 46 //invoke after http handler 47 PostHttpInterceptors []http_.HandlerInterceptor 48 */ 49 } 50 } 51 52 type GRPCGateway struct { 53 grpcServer *grpc.Server 54 http.Server 55 //assigned by ginRouter in PrepareRun 56 Handler http.Handler 57 //gatewayMux for http handler 58 gatewayMux *runtime.ServeMux 59 once sync.Once 60 61 opts struct { 62 interceptionOptions InterceptorOption 63 serverOptions []grpc.ServerOption 64 gatewayMuxOptions []runtime.ServeMuxOption 65 clientDialOptions []grpc.DialOption 66 } 67 } 68 69 func NewGRPCGateWay(addr string, options ...GRPCGatewayOption) *GRPCGateway { 70 server := &GRPCGateway{ 71 Server: http.Server{ 72 Addr: addr, 73 }, 74 } 75 server.ApplyOptions(options...) 76 77 return server 78 } 79 80 func (g *GRPCGateway) initOnce() { 81 g.once.Do(func() { 82 //now not support tls 83 g.opts.clientDialOptions = append(g.opts.clientDialOptions, grpc_.ClientDialOptions()...) 84 85 serverOptions := []grpc.ServerOption{} 86 serverOptions = append( 87 g.opts.serverOptions, 88 grpc.ChainUnaryInterceptor(g.opts.interceptionOptions.grpcServerOpts.unaryInterceptors...), 89 grpc.ChainStreamInterceptor(g.opts.interceptionOptions.grpcServerOpts.streamInterceptors...), 90 ) 91 92 g.opts.gatewayMuxOptions = append(g.opts.gatewayMuxOptions, 93 runtime.WithRoutingErrorHandler( 94 func(ctx context.Context, mux *runtime.ServeMux, 95 marshaler runtime.Marshaler, 96 w http.ResponseWriter, r *http.Request, code int) { 97 98 //g.Handler is gin handler 99 httpHandler := g.Handler 100 if httpHandler == nil { 101 httpHandler = http.DefaultServeMux 102 } 103 104 // NotFound and NotAllowed, use gin handler 105 if code == http.StatusNotFound || code == http.StatusMethodNotAllowed { 106 httpHandler.ServeHTTP(w, r) 107 return 108 } 109 runtime.DefaultRoutingErrorHandler(ctx, mux, marshaler, w, r, code) 110 })) 111 112 g.grpcServer = grpc.NewServer(serverOptions...) 113 g.gatewayMux = runtime.NewServeMux(g.opts.gatewayMuxOptions...) 114 g.Server.Handler = grpcHandlerFunc(g.grpcServer, g) 115 }) 116 } 117 118 // ServeHTTP, wrap g.gateMux httpServerOpts, and called by grpcHandlerFunc 119 func (g *GRPCGateway) ServeHTTP(w http.ResponseWriter, r *http.Request) { 120 g.opts.interceptionOptions.httpServerOpts.handlerChain.WrapH(g.gatewayMux).ServeHTTP(w, r) 121 } 122 123 func (g *GRPCGateway) ListenAndServe() error { 124 g.initOnce() 125 return g.Server.ListenAndServe() 126 } 127 128 func (g *GRPCGateway) registerGRPCFunc(h GRPCHandler) { 129 g.initOnce() 130 h.Register(g.grpcServer) 131 } 132 133 func (g *GRPCGateway) RegisterGRPCHandler(h func(srv *grpc.Server)) { 134 g.initOnce() 135 g.registerGRPCFunc(GRPCHandlerFunc(h)) 136 } 137 138 func (g *GRPCGateway) registerHTTPFunc(ctx context.Context, h HTTPHandler) error { 139 g.initOnce() 140 return h.Register(ctx, g.gatewayMux, g.Server.Addr, g.opts.clientDialOptions) 141 } 142 143 func (g *GRPCGateway) RegisterHTTPHandler(ctx context.Context, 144 h func(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) error, 145 ) error { 146 g.initOnce() 147 return g.registerHTTPFunc(ctx, HTTPHandlerFunc(h)) 148 }