// Copyright 2020-2021 Buf Technologies, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package rpc import ( "context" ) // ServerInfo contains server rpc info. type ServerInfo struct { // Service is the rpc service component. // // May be empty. // Example: "foo.bar.v1" is the service for "/foo.bar.v1/Baz". Service string // Method is the rpc method component. // // May be empty. // Example: "Baz" is the method for "/foo/bar.v1/Baz". Method string } // ServerInterceptor is a server interceptor. type ServerInterceptor interface { Intercept( ctx context.Context, request interface{}, serverInfo *ServerInfo, serverHandler ServerHandler, ) (interface{}, error) } // ServerInterceptorFunc is a function that implements ServerInterceptor. type ServerInterceptorFunc func( ctx context.Context, request interface{}, serverInfo *ServerInfo, serverHandler ServerHandler, ) (interface{}, error) // Intercept implements ServerInterceptor. func (i ServerInterceptorFunc) Intercept( ctx context.Context, request interface{}, serverInfo *ServerInfo, serverHandler ServerHandler, ) (interface{}, error) { return i(ctx, request, serverInfo, serverHandler) } // ServerHandler is a server handler. type ServerHandler interface { Handle( ctx context.Context, request interface{}, ) (interface{}, error) } // ServerHandlerFunc is a function that implements ServerHandler. type ServerHandlerFunc func( ctx context.Context, request interface{}, ) (interface{}, error) // Handle implements ServerHandler. func (h ServerHandlerFunc) Handle( ctx context.Context, request interface{}, ) (interface{}, error) { return h(ctx, request) } // NewChainedServerInterceptor returns a new chained ServerInterceptor. // // Returns nil if interceptors is empty. func NewChainedServerInterceptor(interceptors ...ServerInterceptor) ServerInterceptor { switch n := len(interceptors); n { case 0: return nil case 1: return interceptors[0] default: return ServerInterceptorFunc( func( ctx context.Context, request interface{}, serverInfo *ServerInfo, serverHandler ServerHandler, ) (_ interface{}, retErr error) { chainer := func( currentInterceptor ServerInterceptor, currentHandler ServerHandler, ) ServerHandler { return ServerHandlerFunc( func( currentCtx context.Context, currentRequest interface{}, ) (interface{}, error) { return currentInterceptor.Intercept(currentCtx, currentRequest, serverInfo, currentHandler) }, ) } chainedHandler := serverHandler for i := n - 1; i >= 0; i-- { chainedHandler = chainer(interceptors[i], chainedHandler) } return chainedHandler.Handle(ctx, request) }, ) } }