github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/internal/middleware/chain.go (about)

     1  package middleware
     2  
     3  import (
     4  	"context"
     5  
     6  	"google.golang.org/grpc"
     7  )
     8  
     9  // Vendored from grpc-go-middleware
    10  // These were removed in v2, see: https://github.com/grpc-ecosystem/go-grpc-middleware/pull/385
    11  
    12  // ChainUnaryServer creates a single interceptor out of a chain of many interceptors.
    13  //
    14  // Execution is done in left-to-right order, including passing of context.
    15  // For example ChainUnaryServer(one, two, three) will execute one before two before three, and three
    16  // will see context changes of one and two.
    17  func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor {
    18  	n := len(interceptors)
    19  
    20  	return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
    21  		chainer := func(currentInter grpc.UnaryServerInterceptor, currentHandler grpc.UnaryHandler) grpc.UnaryHandler {
    22  			return func(currentCtx context.Context, currentReq interface{}) (interface{}, error) {
    23  				return currentInter(currentCtx, currentReq, info, currentHandler)
    24  			}
    25  		}
    26  
    27  		chainedHandler := handler
    28  		for i := n - 1; i >= 0; i-- {
    29  			chainedHandler = chainer(interceptors[i], chainedHandler)
    30  		}
    31  
    32  		return chainedHandler(ctx, req)
    33  	}
    34  }
    35  
    36  // ChainStreamServer creates a single interceptor out of a chain of many interceptors.
    37  //
    38  // Execution is done in left-to-right order, including passing of context.
    39  // For example ChainUnaryServer(one, two, three) will execute one before two before three.
    40  // If you want to pass context between interceptors, use WrapServerStream.
    41  func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor {
    42  	n := len(interceptors)
    43  
    44  	return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
    45  		chainer := func(currentInter grpc.StreamServerInterceptor, currentHandler grpc.StreamHandler) grpc.StreamHandler {
    46  			return func(currentSrv interface{}, currentStream grpc.ServerStream) error {
    47  				return currentInter(currentSrv, currentStream, info, currentHandler)
    48  			}
    49  		}
    50  
    51  		chainedHandler := handler
    52  		for i := n - 1; i >= 0; i-- {
    53  			chainedHandler = chainer(interceptors[i], chainedHandler)
    54  		}
    55  
    56  		return chainedHandler(srv, ss)
    57  	}
    58  }