From cc691da0f6f8d24678651b2183f28c1ccbd36297 Mon Sep 17 00:00:00 2001 From: bradub Date: Fri, 10 Mar 2023 09:37:35 +0200 Subject: [PATCH] feat(grpc): add new option that allows cors configuration for the gateway server --- grpc/gateway_server.go | 61 ++++++++++++++------------ grpc/go.mod | 30 ++++++------- grpc/go.sum | 45 +++++++++++++++++++ grpc/grpc_server.go | 37 ++++++++++------ grpc/options.go | 18 ++++++++ grpc/server.go | 96 ++++++++++------------------------------- sentry/sentry_client.go | 20 ++++++--- 7 files changed, 170 insertions(+), 137 deletions(-) diff --git a/grpc/gateway_server.go b/grpc/gateway_server.go index b0ae317..62fa9d1 100644 --- a/grpc/gateway_server.go +++ b/grpc/gateway_server.go @@ -6,6 +6,7 @@ import ( "fmt" "net" "net/http" + "sync/atomic" "time" "contrib.go.opencensus.io/exporter/stackdriver/propagation" @@ -19,14 +20,18 @@ import ( "google.golang.org/grpc/credentials/insecure" ) -var _ server = (*gatewayServer)(nil) - type gatewayServer struct { - internalHTTPServer *http.Server + httpServer *http.Server + listener net.Listener + closed atomic.Bool +} + +func (s *gatewayServer) addr() string { + return s.listener.Addr().String() } -func (s *gatewayServer) Serve(listener net.Listener) error { - err := s.internalHTTPServer.Serve(listener) +func (s *gatewayServer) listenAndServe() error { + err := s.httpServer.Serve(s.listener) if err != nil && !errors.Is(err, http.ErrServerClosed) { return err } @@ -34,20 +39,27 @@ func (s *gatewayServer) Serve(listener net.Listener) error { return nil } -func (s *gatewayServer) Close() error { - return s.internalHTTPServer.Shutdown(context.Background()) +func (s *gatewayServer) close() error { + if s.closed.Load() { + return nil + } + + s.closed.Store(true) + + return s.httpServer.Shutdown(context.Background()) } // nolint: revive // false-positive, it reports tracing as a control flag. -func newGatewayServerWithListener( +func newGatewayServer( muxOptions []runtime.ServeMuxOption, tracing bool, registerGateway registerGatewayFunc, address string, middlewares chi.Middlewares, debugStandardLibraryEndpoints bool, + corsOptions cors.Options, ) ( - *serverWithListener, + *gatewayServer, error, ) { grpcGatewayMux := runtime.NewServeMux( @@ -80,12 +92,7 @@ func newGatewayServerWithListener( return nil, fmt.Errorf("new listener: %w", err) } - corsHandler := cors.New(cors.Options{ - AllowedMethods: []string{"GET", "POST", "PATCH", "PUT", "DELETE"}, - AllowedHeaders: []string{"Accept", "Authorization", "Content-Type"}, - ExposedHeaders: []string{"Link", "X-Total-Count"}, - AllowCredentials: true, - }) + corsHandler := cors.New(corsOptions) router := chi.NewRouter() @@ -115,19 +122,17 @@ func newGatewayServerWithListener( idleTimeout = 2 * time.Minute ) - return &serverWithListener{ - server: &gatewayServer{ - internalHTTPServer: &http.Server{ - Handler: http.TimeoutHandler( - router, - handlerTimeout, - "", - ), - ReadTimeout: readTimeout, - ReadHeaderTimeout: readHeaderTimeout, - WriteTimeout: writeTimeout, - IdleTimeout: idleTimeout, - }, + return &gatewayServer{ + httpServer: &http.Server{ + Handler: http.TimeoutHandler( + router, + handlerTimeout, + "", + ), + ReadTimeout: readTimeout, + ReadHeaderTimeout: readHeaderTimeout, + WriteTimeout: writeTimeout, + IdleTimeout: idleTimeout, }, listener: listener, }, diff --git a/grpc/go.mod b/grpc/go.mod index 2f143d2..8efedb8 100644 --- a/grpc/go.mod +++ b/grpc/go.mod @@ -7,14 +7,14 @@ require ( github.com/go-chi/chi/v5 v5.0.8 github.com/google/uuid v1.3.0 github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 github.com/matryer/is v1.4.0 github.com/oklog/run v1.1.0 github.com/rs/cors v1.8.3 go.opencensus.io v0.24.0 go.uber.org/zap v1.24.0 - google.golang.org/grpc v1.52.3 - google.golang.org/protobuf v1.28.1 + google.golang.org/grpc v1.53.0 + google.golang.org/protobuf v1.29.0 ) require ( @@ -22,23 +22,23 @@ require ( cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/monitoring v1.12.0 // indirect cloud.google.com/go/trace v1.8.0 // indirect - github.com/aws/aws-sdk-go v1.44.189 // indirect + github.com/aws/aws-sdk-go v1.44.218 // indirect github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.1 // indirect - github.com/googleapis/gax-go/v2 v2.7.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect + github.com/googleapis/gax-go/v2 v2.7.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/prometheus/prometheus v0.41.0 // indirect + github.com/prometheus/prometheus v0.42.0 // indirect go.uber.org/atomic v1.10.0 // indirect - go.uber.org/multierr v1.9.0 // indirect - golang.org/x/net v0.5.0 // indirect - golang.org/x/oauth2 v0.4.0 // indirect + go.uber.org/multierr v1.10.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/oauth2 v0.6.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.4.0 // indirect - golang.org/x/text v0.6.0 // indirect - google.golang.org/api v0.108.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect + google.golang.org/api v0.112.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa // indirect + google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect ) diff --git a/grpc/go.sum b/grpc/go.sum index 425ef65..b572b5f 100644 --- a/grpc/go.sum +++ b/grpc/go.sum @@ -38,6 +38,7 @@ cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRY cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= cloud.google.com/go v0.107.0 h1:qkj22L7bgkl6vIeZDlOY2po43Mx/TIa2Wsa7VR+PEww= cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= +cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= @@ -504,6 +505,10 @@ github.com/aws/aws-sdk-go v1.44.186 h1:HInpD2b9FXgJIcP/WDRuSW4Wri9i5WVglO9okFFuO github.com/aws/aws-sdk-go v1.44.186/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go v1.44.189 h1:9PBrjndH1uL5AN8818qI3duhQ4hgkMuLvqkJlg9MRyk= github.com/aws/aws-sdk-go v1.44.189/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.206 h1:xC7O40wdnKH4A95KdYt+smXl9hig1vu9b3mFxAxUoak= +github.com/aws/aws-sdk-go v1.44.206/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.218 h1:p707+xOCazWhkSpZOeyhtTcg7Z+asxxvueGgYPSitn4= +github.com/aws/aws-sdk-go v1.44.218/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v1.9.1/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o= github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= @@ -930,6 +935,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -994,6 +1001,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= github.com/googleapis/enterprise-certificate-proxy v0.2.1 h1:RY7tHKZcRlk788d5WSo/e83gOyyy742E8GSs771ySpg= github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= +github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -1005,6 +1014,8 @@ github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqE github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= +github.com/googleapis/gax-go/v2 v2.7.1 h1:gF4c0zjUP2H/s/hEGyLA3I0fA2ZWjzYiONAD6cvPr8A= +github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= @@ -1040,6 +1051,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.1/go.mod h1:G+WkljZi4mflcqVxYSgv github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.0 h1:1JYBfzqrWPcCclBwxFCPAou9n+q86mfnu7NAeHfte7A= github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.0/go.mod h1:YDZoGHuwE+ov0c8smSH49WLF3F2LaWnYYuDVd+EWrc0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 h1:gDLXvp5S9izjldquuoAhDzccbskOL6tDC5jMSyx3zxE= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2/go.mod h1:7pdNwVWBBHGiCxa9lAszqCJMbfTISJ7oMftp8+UGV08= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= @@ -1420,6 +1433,8 @@ github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0ua github.com/prometheus/prometheus v0.35.0/go.mod h1:7HaLx5kEPKJ0GDgbODG0fZgXbQ8K/XjZNJXQmbmgQlY= github.com/prometheus/prometheus v0.41.0 h1:+QR4QpzwE54zsKk2K7EUkof3tHxa3b/fyw7xJ4jR1Ns= github.com/prometheus/prometheus v0.41.0/go.mod h1:Uu5817xm7ibU/VaDZ9pu1ssGzcpO9Bd+LyoZ76RpHyo= +github.com/prometheus/prometheus v0.42.0 h1:G769v8covTkOiNckXFIwLx01XE04OE6Fr0JPA0oR2nI= +github.com/prometheus/prometheus v0.42.0/go.mod h1:Pfqb/MLnnR2KK+0vchiaH39jXxvLMBk+3lnIGP4N7Vk= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rakyll/embedmd v0.0.0-20171029212350-c8060a0752a2/go.mod h1:7jOTMgqac46PZcF54q6l2hkLEG8op93fZu61KmxWDV4= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -1644,6 +1659,8 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= @@ -1816,6 +1833,10 @@ golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10/go.mod h1:MBQ8lrhLObU/6UmL golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1845,6 +1866,10 @@ golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk= golang.org/x/oauth2 v0.4.0 h1:NF0gk8LVPg1Ml7SSbGyySuoxdsXitj7TvgvuRxIMc/M= golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= +golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= +golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= +golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -2007,6 +2032,10 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -2030,6 +2059,10 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2193,6 +2226,10 @@ google.golang.org/api v0.104.0/go.mod h1:JCspTXJbBxa5ySXw4UgUqVer7DfVxbvc/CTUFqA google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= google.golang.org/api v0.108.0 h1:WVBc/faN0DkKtR43Q/7+tPny9ZoLZdIiAyG5Q9vFClg= google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.110.0 h1:l+rh0KYUooe9JGbGVx71tbFo4SMbMTXK3I3ia2QSEeU= +google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= +google.golang.org/api v0.112.0 h1:iDmzvZ4C086R3+en4nSyIf07HlQKMOX1Xx2dmia/+KQ= +google.golang.org/api v0.112.0/go.mod h1:737UfWHNsOq4F3REUTmb+GN9pugkgNLCayLTfoIKpPc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2331,6 +2368,10 @@ google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2 h1:O97sLx/Xmb/KIZH google.golang.org/genproto v0.0.0-20230124163310-31e0e69b6fc2/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa h1:GZXdWYIKckxQE2EcLHLvF+KLF+bIwoxGdMUxTZizueg= google.golang.org/genproto v0.0.0-20230127162408-596548ed4efa/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20230221151758-ace64dc21148 h1:muK+gVBJBfFb4SejshDBlN2/UgxCCOKH9Y34ljqEGOc= +google.golang.org/genproto v0.0.0-20230221151758-ace64dc21148/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA= +google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -2377,6 +2418,8 @@ google.golang.org/grpc v1.52.1 h1:2NpOPk5g5Xtb0qebIEs7hNIa++PdtZLo2AQUpc1YnSU= google.golang.org/grpc v1.52.1/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/grpc v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ= google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -2394,6 +2437,8 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.29.0 h1:44S3JjaKmLEE4YIkjzexaP+NzZsudE3Zin5Njn/pYX0= +google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/grpc/grpc_server.go b/grpc/grpc_server.go index 820aa95..35aa5ca 100644 --- a/grpc/grpc_server.go +++ b/grpc/grpc_server.go @@ -8,6 +8,7 @@ import ( "os" "path" "strconv" + "sync/atomic" "time" "contrib.go.opencensus.io/exporter/stackdriver" @@ -23,25 +24,35 @@ import ( "google.golang.org/grpc/status" ) -var _ server = (*grpcServer)(nil) - type grpcServer struct { - internalGRPCServer *grpc.Server + grpcServer *grpc.Server + listener net.Listener + closed atomic.Bool +} + +func (s *grpcServer) listenAndServe() error { + return s.grpcServer.Serve(s.listener) } -func (s *grpcServer) Serve(listener net.Listener) error { - return s.internalGRPCServer.Serve(listener) +func (s *grpcServer) addr() string { + return s.listener.Addr().String() } -func (s *grpcServer) Close() error { - s.internalGRPCServer.GracefulStop() +func (s *grpcServer) close() error { + if s.closed.Load() { + return nil + } + + s.closed.Store(true) + + s.grpcServer.GracefulStop() return nil } // nolint: gocyclo, revive // cyclomatic complexity is 9. FIXME // revive complains about tracing being a control flag. -func newGRPCServerWithListener( +func newGRPCServer( listener net.Listener, address string, tracing bool, @@ -53,7 +64,7 @@ func newGRPCServerWithListener( panicHandler PanicHandler, monitorOperationer MonitorOperationer, ) ( - *serverWithListener, + *grpcServer, error, ) { grpcListener, err := newGRPCListener(listener, address) @@ -119,11 +130,9 @@ func newGRPCServerWithListener( registerServer(internalGRPCServer) } - return &serverWithListener{ - server: &grpcServer{ - internalGRPCServer: internalGRPCServer, - }, - listener: grpcListener, + return &grpcServer{ + grpcServer: internalGRPCServer, + listener: grpcListener, }, nil } diff --git a/grpc/options.go b/grpc/options.go index 63d7cfa..7841127 100644 --- a/grpc/options.go +++ b/grpc/options.go @@ -10,6 +10,7 @@ import ( grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" grpc_ctxtags "github.com/grpc-ecosystem/go-grpc-middleware/tags" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" + "github.com/rs/cors" "go.uber.org/zap" "google.golang.org/grpc" "google.golang.org/grpc/metadata" @@ -65,6 +66,7 @@ type serverOptions struct { errorHandler ErrorHandler panicHandler PanicHandler monitorOperationer MonitorOperationer + gatewayCorsOptions cors.Options } // WithAddress configures the Server to listen to the given address @@ -276,6 +278,13 @@ func WithDebugStandardLibraryEndpoints() ServerOption { }) } +// WithGatewayCorsOptions sets the options to be used with CORS for the gateway server. +func WithGatewayCorsOptions(opts cors.Options) ServerOption { + return newFuncServerOption(func(o *serverOptions) { + o.gatewayCorsOptions = opts + }) +} + func defaultServerOptions() serverOptions { return serverOptions{ tracing: false, @@ -306,5 +315,14 @@ func defaultServerOptions() serverOptions { registerGateway: nil, grpcListener: nil, unaryServerInterceptors: nil, + errorHandler: nil, + panicHandler: nil, + monitorOperationer: nil, + gatewayCorsOptions: cors.Options{ + AllowedMethods: []string{"GET", "POST", "PATCH", "PUT", "DELETE"}, + AllowedHeaders: []string{"Accept", "Authorization", "Content-Type"}, + ExposedHeaders: []string{"Link", "X-Total-Count"}, + AllowCredentials: true, + }, } } diff --git a/grpc/server.go b/grpc/server.go index c41a032..79f5aae 100644 --- a/grpc/server.go +++ b/grpc/server.go @@ -3,8 +3,6 @@ package grpc import ( "errors" "fmt" - "io" - "net" "sync" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" @@ -18,22 +16,6 @@ import ( var ErrServerClosed = errors.New("go-commons.grpc: server closed") type ( - // the server interface defines basic methods for starting - // and stopping a server. - server interface { - io.Closer - Serve(listener net.Listener) error - } - - // serverWithListener represents an implemented server - // that can be started and stopped. - serverWithListener struct { - server server - listener net.Listener - running bool - runningMutex sync.Mutex - } - // registerServerFunc defines how we can register // a grpc service to a grpc server. registerServerFunc func(server *grpc.Server) @@ -46,41 +28,12 @@ type ( ) error ) -// ListenAndServe accepts incoming connections on the listener -// available in the struct. -func (s *serverWithListener) ListenAndServe() error { - s.runningMutex.Lock() - - s.running = true - - s.runningMutex.Unlock() - - return s.server.Serve(s.listener) -} - -// Close stops the seerver gracefully. -func (s *serverWithListener) Close() error { - s.runningMutex.Lock() - defer s.runningMutex.Unlock() - - if !s.running { - return nil - } - - err := s.server.Close() - if err != nil { - return err - } - - return nil -} - // Server holds the grpc and gateway underlying servers. // It starts and stops both of them together. // In case one of the server fails the other one is closed. type Server struct { - grpcServerWithListener *serverWithListener - grpcGatewayServerWithListener *serverWithListener + grpcServer *grpcServer + gatewayServer *gatewayServer logging *logging @@ -105,7 +58,7 @@ func NewServer(opt ...ServerOption) (*Server, error) { aggregatorServer.logging = opts.logging } - grpcServerWithListener, err := newGRPCServerWithListener( + grpcServerWithListener, err := newGRPCServer( opts.grpcListener, opts.address, opts.tracing, @@ -121,26 +74,27 @@ func NewServer(opt ...ServerOption) (*Server, error) { return nil, fmt.Errorf("new gRPC server: %w", err) } - aggregatorServer.grpcServerWithListener = grpcServerWithListener + aggregatorServer.grpcServer = grpcServerWithListener // return here if a gateway server is not wanted. if !opts.gateway { return aggregatorServer, nil } - grpcGatewayServer, err := newGatewayServerWithListener( + grpcGatewayServer, err := newGatewayServer( opts.muxOptions, opts.tracing, opts.registerGateway, opts.address, opts.httpMiddlewares, opts.debugStandardLibraryEndpoints, + opts.gatewayCorsOptions, ) if err != nil { return nil, fmt.Errorf("new gRPC gateway server: %w", err) } - aggregatorServer.grpcGatewayServerWithListener = grpcGatewayServer + aggregatorServer.gatewayServer = grpcGatewayServer return aggregatorServer, nil } @@ -151,26 +105,22 @@ func (s *Server) ListenAndServe() error { s.mu.Lock() if s.closed { + s.mu.Unlock() + return ErrServerClosed } var runGroup run.Group - runGroup.Add( - s.runGRPCServer, - func(err error) { - _ = s.grpcServerWithListener.Close() - }, - ) + runGroup.Add(s.runGRPCServer, func(err error) { + _ = s.grpcServer.close() + }) // start gateway server. - if s.grpcGatewayServerWithListener != nil { - runGroup.Add( - s.runGatewayServer, - func(err error) { - _ = s.grpcGatewayServerWithListener.Close() - }, - ) + if s.gatewayServer != nil { + runGroup.Add(s.runGatewayServer, func(err error) { + _ = s.gatewayServer.close() + }) } s.mu.Unlock() @@ -188,18 +138,18 @@ func (s *Server) runGRPCServer() error { "starting gRPC server", zap.String( "address", - s.grpcServerWithListener.listener.Addr().String(), + s.grpcServer.addr(), ), ) - return s.grpcServerWithListener.ListenAndServe() + return s.grpcServer.listenAndServe() } func (s *Server) closeGRPCServer() error { s.logDebug("close grpc server") defer s.logDebug("grpc server done") - return s.grpcServerWithListener.Close() + return s.grpcServer.close() } func (s *Server) runGatewayServer() error { @@ -207,18 +157,18 @@ func (s *Server) runGatewayServer() error { "starting gRPC gateway server for HTTP requests", zap.String( "address", - s.grpcGatewayServerWithListener.listener.Addr().String(), + s.gatewayServer.addr(), ), ) - return s.grpcGatewayServerWithListener.ListenAndServe() + return s.gatewayServer.listenAndServe() } func (s *Server) closeGatewayServer() error { s.logDebug("close gateway server") defer s.logDebug("gateway server done") - return s.grpcGatewayServerWithListener.Close() + return s.gatewayServer.close() } // Close closes both underlying servers. @@ -233,7 +183,7 @@ func (s *Server) Close() error { // 1. Stop GRPC Gateway server first as it sits above GRPC server. // This also closes the underlying grpcListener. - if s.grpcGatewayServerWithListener != nil { + if s.gatewayServer != nil { err := s.closeGatewayServer() if err != nil { return fmt.Errorf("close gateway server: %w", err) diff --git a/sentry/sentry_client.go b/sentry/sentry_client.go index 54e770a..ccb71c6 100644 --- a/sentry/sentry_client.go +++ b/sentry/sentry_client.go @@ -20,8 +20,8 @@ var ( // NewClient returns a new instance of Sentry ReporterService. func NewClient( - dsn, environment, release string, - traceSampleRate float64, + dsn, environment, release string, + traceSampleRate float64, ) (*Client, error) { err := sentry.Init(sentry.ClientOptions{ // Either set your DSN here or set the SENTRY_DSN environment variable. @@ -44,7 +44,13 @@ func NewClient( // ReportError reports an error to Sentry. func (*Client) ReportError(ctx context.Context, err error) error { - eventID := hubFromContext(ctx).CaptureException(err) + hub := hubFromContext(ctx) + + eventID := hub.Client().CaptureException( + err, + &sentry.EventHint{Context: ctx}, + hub.Scope(), + ) if eventID == nil { return ErrNoClientOrScopeAvailable } @@ -65,10 +71,10 @@ func (*Client) ReportEvent(ctx context.Context, event string) error { // MonitorOperation returns a new context to be used with the operation // and a done function to signal that the operation ended. func (*Client) MonitorOperation( - ctx context.Context, - operation string, - traceID [16]byte, - doFunc func(context.Context), + ctx context.Context, + operation string, + traceID [16]byte, + doFunc func(context.Context), ) { hub := sentry.GetHubFromContext(ctx) if hub == nil {