mirror of
https://github.com/linka-cloud/grpc.git
synced 2025-10-19 03:41:46 +00:00
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:
200
interceptors/chain/chain.go
Normal file → Executable file
200
interceptors/chain/chain.go
Normal file → Executable 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
206
interceptors/chain/chain_test.go
Executable 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
125
interceptors/chain/interceptor.go
Executable 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...)
|
||||
}
|
@@ -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)
|
||||
|
@@ -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"
|
||||
|
Reference in New Issue
Block a user