github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/pkg/middleware/serverversion/serverversion.go (about) 1 package serverversion 2 3 import ( 4 "context" 5 6 "github.com/authzed/authzed-go/pkg/requestmeta" 7 "github.com/authzed/authzed-go/pkg/responsemeta" 8 "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors" 9 "google.golang.org/grpc" 10 "google.golang.org/grpc/metadata" 11 12 log "github.com/authzed/spicedb/internal/logging" 13 "github.com/authzed/spicedb/pkg/releases" 14 ) 15 16 // HandleServerVersion defines a middleware for returning the version of the server 17 // when requested via the RequestServerVersion header. 18 type HandleServerVersion struct { 19 // IsEnabled is whether the middleware is enabled. 20 IsEnabled bool 21 22 // GetVersion is the function used to retrieve the service version. 23 GetVersion func() (string, error) 24 } 25 26 func (r *HandleServerVersion) ServerReporter(ctx context.Context, _ interceptors.CallMeta) (interceptors.Reporter, context.Context) { 27 if r.IsEnabled { 28 if md, ok := metadata.FromIncomingContext(ctx); ok { 29 if _, isRequestingVersion := md[string(requestmeta.RequestServerVersion)]; isRequestingVersion { 30 version, err := r.GetVersion() 31 if err != nil { 32 log.Ctx(ctx).Err(err).Msg("could not load current service version") 33 return interceptors.NoopReporter{}, ctx 34 } 35 36 err = responsemeta.SetResponseHeaderMetadata(ctx, map[responsemeta.ResponseMetadataHeaderKey]string{ 37 responsemeta.ServerVersion: version, 38 }) 39 // if context is cancelled, the stream will be closed, and gRPC will return ErrIllegalHeaderWrite 40 // this prevents logging unnecessary error messages 41 if err := ctx.Err(); err != nil { 42 return interceptors.NoopReporter{}, ctx 43 } 44 if err != nil { 45 log.Ctx(ctx).Warn().Err(err).Msg("serverversion: could not report metadata") 46 } 47 } 48 } 49 } 50 51 return interceptors.NoopReporter{}, ctx 52 } 53 54 // UnaryServerInterceptor returns a new interceptor which handles server version requests. 55 func UnaryServerInterceptor(isEnabled bool) grpc.UnaryServerInterceptor { 56 return interceptors.UnaryServerInterceptor(&HandleServerVersion{isEnabled, releases.CurrentVersion}) 57 } 58 59 // StreamServerInterceptor returns a new interceptor which handles server version requests. 60 func StreamServerInterceptor(isEnabled bool) grpc.StreamServerInterceptor { 61 return interceptors.StreamServerInterceptor(&HandleServerVersion{isEnabled, releases.CurrentVersion}) 62 }