chore(deps): remove direct dependency on github.com/grpc-ecosystem/go-grpc-middleware (v1)

Signed-off-by: Adphi <philippe.adrien.nousse@gmail.com>
This commit is contained in:
2025-08-01 09:54:53 +02:00
parent 52083569c5
commit cf1208304a
11 changed files with 460 additions and 128 deletions

200
interceptors/chain/chain.go Normal file → Executable file
View File

@@ -1,126 +1,148 @@
// Copyright 2016 Michal Witkowski. All Rights Reserved.
// See LICENSE for licensing terms.
// gRPC Server Interceptor chaining middleware.
package chain
import (
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
"google.golang.org/grpc"
"context"
"go.linka.cloud/grpc-toolkit/interceptors"
"google.golang.org/grpc"
)
type Option func(*chain)
// UnaryServer creates a single interceptor out of a chain of many interceptors.
//
// Execution is done in left-to-right order, including passing of context.
// For example UnaryServer(one, two, three) will execute one before two before three, and three
// will see context changes of one and two.
//
// While this can be useful in some scenarios, it is generally advisable to use google.golang.org/grpc.ChainUnaryInterceptor directly.
func UnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor {
n := len(interceptors)
func WithInterceptors(i ...interceptors.Interceptors) Option {
return func(c *chain) {
for _, i := range i {
if i := i.UnaryServerInterceptor(); i != nil {
c.usi = append(c.usi, i)
}
if i := i.StreamServerInterceptor(); i != nil {
c.ssi = append(c.ssi, i)
}
if i := i.UnaryClientInterceptor(); i != nil {
c.uci = append(c.uci, i)
}
if i := i.StreamClientInterceptor(); i != nil {
c.sci = append(c.sci, i)
}
// Dummy interceptor maintained for backward compatibility to avoid returning nil.
if n == 0 {
return func(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
return handler(ctx, req)
}
}
}
func WithServerInterceptors(si ...interceptors.ServerInterceptors) Option {
return func(c *chain) {
for _, i := range si {
if i := i.UnaryServerInterceptor(); i != nil {
c.usi = append(c.usi, i)
}
if i := i.StreamServerInterceptor(); i != nil {
c.ssi = append(c.ssi, i)
// The degenerate case, just return the single wrapped interceptor directly.
if n == 1 {
return interceptors[0]
}
// Return a function which satisfies the interceptor interface, and which is
// a closure over the given list of interceptors to be chained.
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
currHandler := handler
// Iterate backwards through all interceptors except the first (outermost).
// Wrap each one in a function which satisfies the handler interface, but
// is also a closure over the `info` and `handler` parameters. Then pass
// each pseudo-handler to the next outer interceptor as the handler to be called.
for i := n - 1; i > 0; i-- {
// Rebind to loop-local vars so they can be closed over.
innerHandler, i := currHandler, i
currHandler = func(currentCtx context.Context, currentReq interface{}) (interface{}, error) {
return interceptors[i](currentCtx, currentReq, info, innerHandler)
}
}
// Finally return the result of calling the outermost interceptor with the
// outermost pseudo-handler created above as its handler.
return interceptors[0](ctx, req, info, currHandler)
}
}
func WithClientInterceptors(ci ...interceptors.ClientInterceptors) Option {
return func(c *chain) {
for _, i := range ci {
if i := i.UnaryClientInterceptor(); i != nil {
c.uci = append(c.uci, i)
}
if i := i.StreamClientInterceptor(); i != nil {
c.sci = append(c.sci, i)
}
// StreamServer creates a single interceptor out of a chain of many interceptors.
//
// Execution is done in left-to-right order, including passing of context.
// For example UnaryServer(one, two, three) will execute one before two before three.
// If you want to pass context between interceptors, use WrapServerStream.
//
// While this can be useful in some scenarios, it is generally advisable to use google.golang.org/grpc.ChainStreamInterceptor directly.
func StreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor {
n := len(interceptors)
// Dummy interceptor maintained for backward compatibility to avoid returning nil.
if n == 0 {
return func(srv interface{}, stream grpc.ServerStream, _ *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
return handler(srv, stream)
}
}
}
func WithUnaryServerInterceptors(usi ...grpc.UnaryServerInterceptor) Option {
return func(c *chain) {
for _, i := range usi {
if i != nil {
c.usi = append(c.usi, i)
if n == 1 {
return interceptors[0]
}
return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
currHandler := handler
for i := n - 1; i > 0; i-- {
innerHandler, i := currHandler, i
currHandler = func(currentSrv interface{}, currentStream grpc.ServerStream) error {
return interceptors[i](currentSrv, currentStream, info, innerHandler)
}
}
return interceptors[0](srv, stream, info, currHandler)
}
}
func WithStreamServerInterceptors(ssi ...grpc.StreamServerInterceptor) Option {
return func(c *chain) {
for _, i := range ssi {
if i != nil {
c.ssi = append(c.ssi, i)
}
// UnaryClient creates a single interceptor out of a chain of many interceptors.
//
// Execution is done in left-to-right order, including passing of context.
// For example UnaryClient(one, two, three) will execute one before two before three.
func UnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor {
n := len(interceptors)
// Dummy interceptor maintained for backward compatibility to avoid returning nil.
if n == 0 {
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
return invoker(ctx, method, req, reply, cc, opts...)
}
}
}
func WithUnaryClientInterceptors(uci ...grpc.UnaryClientInterceptor) Option {
return func(c *chain) {
for _, i := range uci {
if i != nil {
c.uci = append(c.uci, i)
if n == 1 {
return interceptors[0]
}
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
currInvoker := invoker
for i := n - 1; i > 0; i-- {
innerInvoker, i := currInvoker, i
currInvoker = func(currentCtx context.Context, currentMethod string, currentReq, currentRepl interface{}, currentConn *grpc.ClientConn, currentOpts ...grpc.CallOption) error {
return interceptors[i](currentCtx, currentMethod, currentReq, currentRepl, currentConn, innerInvoker, currentOpts...)
}
}
return interceptors[0](ctx, method, req, reply, cc, currInvoker, opts...)
}
}
func WithStreamClientInterceptors(sci ...grpc.StreamClientInterceptor) Option {
return func(c *chain) {
for _, i := range sci {
if i != nil {
c.sci = append(c.sci, i)
}
// StreamClient creates a single interceptor out of a chain of many interceptors.
//
// Execution is done in left-to-right order, including passing of context.
// For example StreamClient(one, two, three) will execute one before two before three.
func StreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor {
n := len(interceptors)
// Dummy interceptor maintained for backward compatibility to avoid returning nil.
if n == 0 {
return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
return streamer(ctx, desc, cc, method, opts...)
}
}
}
func New(opts ...Option) interceptors.Interceptors {
c := &chain{}
for _, o := range opts {
o(c)
if n == 1 {
return interceptors[0]
}
return c
}
type chain struct {
usi []grpc.UnaryServerInterceptor
ssi []grpc.StreamServerInterceptor
uci []grpc.UnaryClientInterceptor
sci []grpc.StreamClientInterceptor
}
func (c *chain) UnaryServerInterceptor() grpc.UnaryServerInterceptor {
return grpc_middleware.ChainUnaryServer(c.usi...)
}
func (c *chain) StreamServerInterceptor() grpc.StreamServerInterceptor {
return grpc_middleware.ChainStreamServer(c.ssi...)
}
func (c *chain) UnaryClientInterceptor() grpc.UnaryClientInterceptor {
return grpc_middleware.ChainUnaryClient(c.uci...)
}
func (c *chain) StreamClientInterceptor() grpc.StreamClientInterceptor {
return grpc_middleware.ChainStreamClient(c.sci...)
return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
currStreamer := streamer
for i := n - 1; i > 0; i-- {
innerStreamer, i := currStreamer, i
currStreamer = func(currentCtx context.Context, currentDesc *grpc.StreamDesc, currentConn *grpc.ClientConn, currentMethod string, currentOpts ...grpc.CallOption) (grpc.ClientStream, error) {
return interceptors[i](currentCtx, currentDesc, currentConn, currentMethod, innerStreamer, currentOpts...)
}
}
return interceptors[0](ctx, desc, cc, method, currStreamer, opts...)
}
}

206
interceptors/chain/chain_test.go Executable file
View File

@@ -0,0 +1,206 @@
// Copyright 2016 Michal Witkowski. All Rights Reserved.
// See LICENSE for licensing terms.
package chain
import (
"context"
"fmt"
"testing"
"github.com/stretchr/testify/require"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"go.linka.cloud/grpc-toolkit/interceptors"
)
var (
someServiceName = "SomeService.StreamMethod"
parentUnaryInfo = &grpc.UnaryServerInfo{FullMethod: someServiceName}
parentStreamInfo = &grpc.StreamServerInfo{
FullMethod: someServiceName,
IsServerStream: true,
}
someValue = 1
parentContext = context.WithValue(context.TODO(), "parent", someValue)
)
func TestChainUnaryServer(t *testing.T) {
input := "input"
output := "output"
first := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
requireContextValue(t, ctx, "parent", "first interceptor must know the parent context value")
require.Equal(t, parentUnaryInfo, info, "first interceptor must know the someUnaryServerInfo")
ctx = context.WithValue(ctx, "first", 1)
return handler(ctx, req)
}
second := func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
requireContextValue(t, ctx, "parent", "second interceptor must know the parent context value")
requireContextValue(t, ctx, "first", "second interceptor must know the first context value")
require.Equal(t, parentUnaryInfo, info, "second interceptor must know the someUnaryServerInfo")
ctx = context.WithValue(ctx, "second", 1)
return handler(ctx, req)
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
require.EqualValues(t, input, req, "handler must get the input")
requireContextValue(t, ctx, "parent", "handler must know the parent context value")
requireContextValue(t, ctx, "first", "handler must know the first context value")
requireContextValue(t, ctx, "second", "handler must know the second context value")
return output, nil
}
chain := UnaryServer(first, second)
out, _ := chain(parentContext, input, parentUnaryInfo, handler)
require.EqualValues(t, output, out, "chain must return handler's output")
}
func TestChainStreamServer(t *testing.T) {
someService := &struct{}{}
recvMessage := "received"
sentMessage := "sent"
outputError := fmt.Errorf("some error")
first := func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
requireContextValue(t, stream.Context(), "parent", "first interceptor must know the parent context value")
require.Equal(t, parentStreamInfo, info, "first interceptor must know the parentStreamInfo")
require.Equal(t, someService, srv, "first interceptor must know someService")
wrapped := interceptors.NewContextServerStream(context.WithValue(stream.Context(), "first", 1), stream)
return handler(srv, wrapped)
}
second := func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
requireContextValue(t, stream.Context(), "parent", "second interceptor must know the parent context value")
requireContextValue(t, stream.Context(), "first", "second interceptor must know the first context value")
require.Equal(t, parentStreamInfo, info, "second interceptor must know the parentStreamInfo")
require.Equal(t, someService, srv, "second interceptor must know someService")
wrapped := interceptors.NewContextServerStream(context.WithValue(stream.Context(), "second", 1), stream)
return handler(srv, wrapped)
}
handler := func(srv interface{}, stream grpc.ServerStream) error {
require.Equal(t, someService, srv, "handler must know someService")
requireContextValue(t, stream.Context(), "parent", "handler must know the parent context value")
requireContextValue(t, stream.Context(), "first", "handler must know the first context value")
requireContextValue(t, stream.Context(), "second", "handler must know the second context value")
require.NoError(t, stream.RecvMsg(recvMessage), "handler must have access to stream messages")
require.NoError(t, stream.SendMsg(sentMessage), "handler must be able to send stream messages")
return outputError
}
fakeStream := &fakeServerStream{ctx: parentContext, recvMessage: recvMessage}
chain := StreamServer(first, second)
err := chain(someService, fakeStream, parentStreamInfo, handler)
require.Equal(t, outputError, err, "chain must return handler's error")
require.Equal(t, sentMessage, fakeStream.sentMessage, "handler's sent message must propagate to stream")
}
func TestChainUnaryClient(t *testing.T) {
ignoredMd := metadata.Pairs("foo", "bar")
parentOpts := []grpc.CallOption{grpc.Header(&ignoredMd)}
reqMessage := "request"
replyMessage := "reply"
outputError := fmt.Errorf("some error")
first := func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
requireContextValue(t, ctx, "parent", "first must know the parent context value")
require.Equal(t, someServiceName, method, "first must know someService")
require.Len(t, opts, 1, "first should see parent CallOptions")
wrappedCtx := context.WithValue(ctx, "first", 1)
return invoker(wrappedCtx, method, req, reply, cc, opts...)
}
second := func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
requireContextValue(t, ctx, "parent", "second must know the parent context value")
requireContextValue(t, ctx, "first", "second must know the first context value")
require.Equal(t, someServiceName, method, "second must know someService")
require.Len(t, opts, 1, "second should see parent CallOptions")
wrappedOpts := append(opts, grpc.WaitForReady(false))
wrappedCtx := context.WithValue(ctx, "second", 1)
return invoker(wrappedCtx, method, req, reply, cc, wrappedOpts...)
}
invoker := func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, opts ...grpc.CallOption) error {
require.Equal(t, someServiceName, method, "invoker must know someService")
requireContextValue(t, ctx, "parent", "invoker must know the parent context value")
requireContextValue(t, ctx, "first", "invoker must know the first context value")
requireContextValue(t, ctx, "second", "invoker must know the second context value")
require.Len(t, opts, 2, "invoker should see both CallOpts from second and parent")
return outputError
}
chain := UnaryClient(first, second)
err := chain(parentContext, someServiceName, reqMessage, replyMessage, nil, invoker, parentOpts...)
require.Equal(t, outputError, err, "chain must return invokers's error")
}
func TestChainStreamClient(t *testing.T) {
ignoredMd := metadata.Pairs("foo", "bar")
parentOpts := []grpc.CallOption{grpc.Header(&ignoredMd)}
clientStream := &fakeClientStream{}
fakeStreamDesc := &grpc.StreamDesc{ClientStreams: true, ServerStreams: true, StreamName: someServiceName}
first := func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
requireContextValue(t, ctx, "parent", "first must know the parent context value")
require.Equal(t, someServiceName, method, "first must know someService")
require.Len(t, opts, 1, "first should see parent CallOptions")
wrappedCtx := context.WithValue(ctx, "first", 1)
return streamer(wrappedCtx, desc, cc, method, opts...)
}
second := func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
requireContextValue(t, ctx, "parent", "second must know the parent context value")
requireContextValue(t, ctx, "first", "second must know the first context value")
require.Equal(t, someServiceName, method, "second must know someService")
require.Len(t, opts, 1, "second should see parent CallOptions")
wrappedOpts := append(opts, grpc.WaitForReady(false))
wrappedCtx := context.WithValue(ctx, "second", 1)
return streamer(wrappedCtx, desc, cc, method, wrappedOpts...)
}
streamer := func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, opts ...grpc.CallOption) (grpc.ClientStream, error) {
require.Equal(t, someServiceName, method, "streamer must know someService")
require.Equal(t, fakeStreamDesc, desc, "streamer must see the right StreamDesc")
requireContextValue(t, ctx, "parent", "streamer must know the parent context value")
requireContextValue(t, ctx, "first", "streamer must know the first context value")
requireContextValue(t, ctx, "second", "streamer must know the second context value")
require.Len(t, opts, 2, "streamer should see both CallOpts from second and parent")
return clientStream, nil
}
chain := StreamClient(first, second)
someStream, err := chain(parentContext, fakeStreamDesc, nil, someServiceName, streamer, parentOpts...)
require.NoError(t, err, "chain must not return an error")
require.Equal(t, clientStream, someStream, "chain must return invokers's clientstream")
}
func requireContextValue(t *testing.T, ctx context.Context, key string, msg ...interface{}) {
val := ctx.Value(key)
require.NotNil(t, val, msg...)
require.Equal(t, someValue, val, msg...)
}
type fakeServerStream struct {
grpc.ServerStream
ctx context.Context
recvMessage interface{}
sentMessage interface{}
}
func (f *fakeServerStream) Context() context.Context {
return f.ctx
}
func (f *fakeServerStream) SendMsg(m interface{}) error {
if f.sentMessage != nil {
return status.Errorf(codes.AlreadyExists, "fakeServerStream only takes one message, sorry")
}
f.sentMessage = m
return nil
}
func (f *fakeServerStream) RecvMsg(m interface{}) error {
if f.recvMessage == nil {
return status.Errorf(codes.NotFound, "fakeServerStream has no message, sorry")
}
return nil
}
type fakeClientStream struct {
grpc.ClientStream
}

125
interceptors/chain/interceptor.go Executable file
View File

@@ -0,0 +1,125 @@
package chain
import (
"google.golang.org/grpc"
"go.linka.cloud/grpc-toolkit/interceptors"
)
type Option func(*chain)
func WithInterceptors(i ...interceptors.Interceptors) Option {
return func(c *chain) {
for _, i := range i {
if i := i.UnaryServerInterceptor(); i != nil {
c.usi = append(c.usi, i)
}
if i := i.StreamServerInterceptor(); i != nil {
c.ssi = append(c.ssi, i)
}
if i := i.UnaryClientInterceptor(); i != nil {
c.uci = append(c.uci, i)
}
if i := i.StreamClientInterceptor(); i != nil {
c.sci = append(c.sci, i)
}
}
}
}
func WithServerInterceptors(si ...interceptors.ServerInterceptors) Option {
return func(c *chain) {
for _, i := range si {
if i := i.UnaryServerInterceptor(); i != nil {
c.usi = append(c.usi, i)
}
if i := i.StreamServerInterceptor(); i != nil {
c.ssi = append(c.ssi, i)
}
}
}
}
func WithClientInterceptors(ci ...interceptors.ClientInterceptors) Option {
return func(c *chain) {
for _, i := range ci {
if i := i.UnaryClientInterceptor(); i != nil {
c.uci = append(c.uci, i)
}
if i := i.StreamClientInterceptor(); i != nil {
c.sci = append(c.sci, i)
}
}
}
}
func WithUnaryServerInterceptors(usi ...grpc.UnaryServerInterceptor) Option {
return func(c *chain) {
for _, i := range usi {
if i != nil {
c.usi = append(c.usi, i)
}
}
}
}
func WithStreamServerInterceptors(ssi ...grpc.StreamServerInterceptor) Option {
return func(c *chain) {
for _, i := range ssi {
if i != nil {
c.ssi = append(c.ssi, i)
}
}
}
}
func WithUnaryClientInterceptors(uci ...grpc.UnaryClientInterceptor) Option {
return func(c *chain) {
for _, i := range uci {
if i != nil {
c.uci = append(c.uci, i)
}
}
}
}
func WithStreamClientInterceptors(sci ...grpc.StreamClientInterceptor) Option {
return func(c *chain) {
for _, i := range sci {
if i != nil {
c.sci = append(c.sci, i)
}
}
}
}
func New(opts ...Option) interceptors.Interceptors {
c := &chain{}
for _, o := range opts {
o(c)
}
return c
}
type chain struct {
usi []grpc.UnaryServerInterceptor
ssi []grpc.StreamServerInterceptor
uci []grpc.UnaryClientInterceptor
sci []grpc.StreamClientInterceptor
}
func (c *chain) UnaryServerInterceptor() grpc.UnaryServerInterceptor {
return UnaryServer(c.usi...)
}
func (c *chain) StreamServerInterceptor() grpc.StreamServerInterceptor {
return StreamServer(c.ssi...)
}
func (c *chain) UnaryClientInterceptor() grpc.UnaryClientInterceptor {
return UnaryClient(c.uci...)
}
func (c *chain) StreamClientInterceptor() grpc.StreamClientInterceptor {
return StreamClient(c.sci...)
}

View File

@@ -3,11 +3,11 @@ package logging
import (
"context"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/logging"
"google.golang.org/grpc"
"go.linka.cloud/grpc-toolkit/interceptors"
"go.linka.cloud/grpc-toolkit/interceptors/chain"
"go.linka.cloud/grpc-toolkit/logger"
)
@@ -36,7 +36,7 @@ type interceptor struct {
}
func (i *interceptor) UnaryServerInterceptor() grpc.UnaryServerInterceptor {
return grpc_middleware.ChainUnaryServer(
return chain.UnaryServer(
logging.UnaryServerInterceptor(i.log, i.opts...),
func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
log := logger.C(ctx)
@@ -46,7 +46,7 @@ func (i *interceptor) UnaryServerInterceptor() grpc.UnaryServerInterceptor {
}
func (i *interceptor) StreamServerInterceptor() grpc.StreamServerInterceptor {
return grpc_middleware.ChainStreamServer(
return chain.StreamServer(
logging.StreamServerInterceptor(i.log, i.opts...),
func(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
ctx := ss.Context()
@@ -57,7 +57,7 @@ func (i *interceptor) StreamServerInterceptor() grpc.StreamServerInterceptor {
}
func (i *interceptor) UnaryClientInterceptor() grpc.UnaryClientInterceptor {
return grpc_middleware.ChainUnaryClient(
return chain.UnaryClient(
logging.UnaryClientInterceptor(i.log, i.opts...),
func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
log := logger.C(ctx)
@@ -67,7 +67,7 @@ func (i *interceptor) UnaryClientInterceptor() grpc.UnaryClientInterceptor {
}
func (i *interceptor) StreamClientInterceptor() grpc.StreamClientInterceptor {
return grpc_middleware.ChainStreamClient(
return chain.StreamClient(
logging.StreamClientInterceptor(i.log, i.opts...),
func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
log := logger.C(ctx)

View File

@@ -1,7 +1,7 @@
package recovery
import (
grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/recovery"
"google.golang.org/grpc"
"go.linka.cloud/grpc-toolkit/interceptors"