diff --git a/README.md b/README.md
index c70eea6..e52a240 100644
--- a/README.md
+++ b/README.md
@@ -64,7 +64,7 @@ var (
```
-## func [AddStreamClientInterceptor]()
+## func [AddStreamClientInterceptor]()
```go
func AddStreamClientInterceptor(ctx context.Context, i ...grpc.StreamClientInterceptor)
@@ -73,7 +73,7 @@ func AddStreamClientInterceptor(ctx context.Context, i ...grpc.StreamClientInter
AddStreamClientInterceptor adds a client stream interceptor to default client stream interceptors. Must be called during initialization, before any RPCs are made. Not safe for concurrent use.
-## func [AddStreamServerInterceptor]()
+## func [AddStreamServerInterceptor]()
```go
func AddStreamServerInterceptor(ctx context.Context, i ...grpc.StreamServerInterceptor)
@@ -82,7 +82,7 @@ func AddStreamServerInterceptor(ctx context.Context, i ...grpc.StreamServerInter
AddStreamServerInterceptor adds a server interceptor to default server interceptors. Must be called during initialization, before the server starts. Not safe for concurrent use.
-## func [AddUnaryClientInterceptor]()
+## func [AddUnaryClientInterceptor]()
```go
func AddUnaryClientInterceptor(ctx context.Context, i ...grpc.UnaryClientInterceptor)
@@ -91,7 +91,7 @@ func AddUnaryClientInterceptor(ctx context.Context, i ...grpc.UnaryClientInterce
AddUnaryClientInterceptor adds a client interceptor to default client interceptors. Must be called during initialization, before any RPCs are made. Not safe for concurrent use.
-## func [AddUnaryServerInterceptor]()
+## func [AddUnaryServerInterceptor]()
```go
func AddUnaryServerInterceptor(ctx context.Context, i ...grpc.UnaryServerInterceptor)
@@ -100,7 +100,7 @@ func AddUnaryServerInterceptor(ctx context.Context, i ...grpc.UnaryServerInterce
AddUnaryServerInterceptor adds a server interceptor to default server interceptors. Must be called during initialization, before the server starts. Not safe for concurrent use.
-## func [DebugLoggingInterceptor]()
+## func [DebugLoggingInterceptor]()
```go
func DebugLoggingInterceptor() grpc.UnaryServerInterceptor
@@ -109,7 +109,7 @@ func DebugLoggingInterceptor() grpc.UnaryServerInterceptor
DebugLoggingInterceptor is the interceptor that logs all request/response from a handler
-## func [DefaultClientInterceptor]()
+## func [DefaultClientInterceptor]()
```go
func DefaultClientInterceptor(defaultOpts ...interface{}) grpc.UnaryClientInterceptor
@@ -118,7 +118,7 @@ func DefaultClientInterceptor(defaultOpts ...interface{}) grpc.UnaryClientInterc
DefaultClientInterceptor are the set of default interceptors that should be applied to all client calls
-## func [DefaultClientInterceptors]()
+## func [DefaultClientInterceptors]()
```go
func DefaultClientInterceptors(defaultOpts ...interface{}) []grpc.UnaryClientInterceptor
@@ -127,7 +127,7 @@ func DefaultClientInterceptors(defaultOpts ...interface{}) []grpc.UnaryClientInt
DefaultClientInterceptors are the set of default interceptors that should be applied to all client calls
-## func [DefaultClientStreamInterceptor]()
+## func [DefaultClientStreamInterceptor]()
```go
func DefaultClientStreamInterceptor(defaultOpts ...interface{}) grpc.StreamClientInterceptor
@@ -136,7 +136,7 @@ func DefaultClientStreamInterceptor(defaultOpts ...interface{}) grpc.StreamClien
DefaultClientStreamInterceptor are the set of default interceptors that should be applied to all stream client calls
-## func [DefaultClientStreamInterceptors]()
+## func [DefaultClientStreamInterceptors]()
```go
func DefaultClientStreamInterceptors(defaultOpts ...interface{}) []grpc.StreamClientInterceptor
@@ -145,7 +145,7 @@ func DefaultClientStreamInterceptors(defaultOpts ...interface{}) []grpc.StreamCl
DefaultClientStreamInterceptors are the set of default interceptors that should be applied to all stream client calls
-## func [DefaultInterceptors]()
+## func [DefaultInterceptors]()
```go
func DefaultInterceptors() []grpc.UnaryServerInterceptor
@@ -154,7 +154,7 @@ func DefaultInterceptors() []grpc.UnaryServerInterceptor
DefaultInterceptors are the set of default interceptors that are applied to all coldbrew methods
-## func [DefaultStreamInterceptors]()
+## func [DefaultStreamInterceptors]()
```go
func DefaultStreamInterceptors() []grpc.StreamServerInterceptor
@@ -163,33 +163,16 @@ func DefaultStreamInterceptors() []grpc.StreamServerInterceptor
DefaultStreamInterceptors are the set of default interceptors that should be applied to all coldbrew streams
-## func [DoHTTPtoGRPC]()
+## func [DoHTTPtoGRPC]()
```go
func DoHTTPtoGRPC(ctx context.Context, svr interface{}, handler func(ctx context.Context, req interface{}) (interface{}, error), in interface{}) (interface{}, error)
```
-DoHTTPtoGRPC allows calling the interceptors when you use the Register\HandlerServer in grpc\-gateway, see example below for reference
-```
-func (s *svc) Echo(ctx context.Context, req *proto.EchoRequest) (*proto.EchoResponse, error) {
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
- return s.echo(ctx, req.(*proto.EchoRequest))
- }
- r, e := doHTTPtoGRPC(ctx, s, handler, req)
- if e != nil {
- return nil, e.(error)
- }
- return r.(*proto.EchoResponse), nil
-}
-
-func (s *svc) echo(ctx context.Context, req *proto.EchoRequest) (*proto.EchoResponse, error) {
- .... implementation ....
-}
-```
-## func [FilterMethodsFunc]()
+## func [FilterMethodsFunc]()
```go
func FilterMethodsFunc(ctx context.Context, fullMethodName string) bool
@@ -198,7 +181,7 @@ func FilterMethodsFunc(ctx context.Context, fullMethodName string) bool
FilterMethodsFunc is the default implementation of Filter function
-## func [GRPCClientInterceptor]()
+## func [GRPCClientInterceptor]()
```go
func GRPCClientInterceptor(options ...grpc_opentracing.Option) grpc.UnaryClientInterceptor
@@ -207,7 +190,7 @@ func GRPCClientInterceptor(options ...grpc_opentracing.Option) grpc.UnaryClientI
GRPCClientInterceptor is the interceptor that intercepts all cleint requests and adds tracing info to them
-## func [HystrixClientInterceptor]()
+## func [HystrixClientInterceptor]()
```go
func HystrixClientInterceptor(defaultOpts ...grpc.CallOption) grpc.UnaryClientInterceptor
@@ -220,7 +203,7 @@ Note: This interceptor wraps github.com/afex/hystrix\-go which has been unmainta
The interceptor applies provided default and per\-call client options to configure Hystrix behavior \(for example the command name, disabled flag, excluded errors, and excluded gRPC status codes\). If Hystrix is disabled via options, the RPC is invoked directly. If the underlying RPC returns an error that matches any configured excluded error or whose gRPC status code matches any configured excluded code, Hystrix fallback is skipped and the RPC error is returned. Panics raised during the RPC invocation are captured and reported to the notifier before being converted into an error. If the RPC itself returns an error, that error is returned; otherwise any error produced by Hystrix is returned.
-## func [NRHttpTracer]()
+## func [NRHttpTracer]()
```go
func NRHttpTracer(pattern string, h http.HandlerFunc) (string, http.HandlerFunc)
@@ -229,7 +212,7 @@ func NRHttpTracer(pattern string, h http.HandlerFunc) (string, http.HandlerFunc)
NRHttpTracer adds newrelic tracing to this http function
-## func [NewRelicClientInterceptor]()
+## func [NewRelicClientInterceptor]()
```go
func NewRelicClientInterceptor() grpc.UnaryClientInterceptor
@@ -238,7 +221,7 @@ func NewRelicClientInterceptor() grpc.UnaryClientInterceptor
NewRelicClientInterceptor intercepts all client actions and reports them to newrelic
-## func [NewRelicInterceptor]()
+## func [NewRelicInterceptor]()
```go
func NewRelicInterceptor() grpc.UnaryServerInterceptor
@@ -247,7 +230,7 @@ func NewRelicInterceptor() grpc.UnaryServerInterceptor
NewRelicInterceptor intercepts all server actions and reports them to newrelic
-## func [OptionsInterceptor]()
+## func [OptionsInterceptor]()
```go
func OptionsInterceptor() grpc.UnaryServerInterceptor
@@ -256,7 +239,7 @@ func OptionsInterceptor() grpc.UnaryServerInterceptor
-## func [PanicRecoveryInterceptor]()
+## func [PanicRecoveryInterceptor]()
```go
func PanicRecoveryInterceptor() grpc.UnaryServerInterceptor
@@ -265,7 +248,7 @@ func PanicRecoveryInterceptor() grpc.UnaryServerInterceptor
-## func [ResponseTimeLoggingInterceptor]()
+## func [ResponseTimeLoggingInterceptor]()
```go
func ResponseTimeLoggingInterceptor(ff FilterFunc) grpc.UnaryServerInterceptor
@@ -274,7 +257,7 @@ func ResponseTimeLoggingInterceptor(ff FilterFunc) grpc.UnaryServerInterceptor
ResponseTimeLoggingInterceptor logs response time for each request on server
-## func [ResponseTimeLoggingStreamInterceptor]()
+## func [ResponseTimeLoggingStreamInterceptor]()
```go
func ResponseTimeLoggingStreamInterceptor() grpc.StreamServerInterceptor
@@ -283,7 +266,7 @@ func ResponseTimeLoggingStreamInterceptor() grpc.StreamServerInterceptor
ResponseTimeLoggingStreamInterceptor logs response time for stream RPCs.
-## func [ServerErrorInterceptor]()
+## func [ServerErrorInterceptor]()
```go
func ServerErrorInterceptor() grpc.UnaryServerInterceptor
@@ -292,7 +275,7 @@ func ServerErrorInterceptor() grpc.UnaryServerInterceptor
ServerErrorInterceptor intercepts all server actions and reports them to error notifier
-## func [ServerErrorStreamInterceptor]()
+## func [ServerErrorStreamInterceptor]()
```go
func ServerErrorStreamInterceptor() grpc.StreamServerInterceptor
@@ -301,7 +284,7 @@ func ServerErrorStreamInterceptor() grpc.StreamServerInterceptor
ServerErrorStreamInterceptor intercepts server errors for stream RPCs and reports them to the error notifier.
-## func [SetFilterFunc]()
+## func [SetFilterFunc]()
```go
func SetFilterFunc(ctx context.Context, ff FilterFunc)
@@ -310,7 +293,7 @@ func SetFilterFunc(ctx context.Context, ff FilterFunc)
SetFilterFunc sets the default filter function to be used by interceptors. Must be called during initialization, before the server starts. Not safe for concurrent use.
-## func [SetResponseTimeLogLevel]()
+## func [SetResponseTimeLogLevel]()
```go
func SetResponseTimeLogLevel(ctx context.Context, level loggers.Level)
@@ -319,7 +302,7 @@ func SetResponseTimeLogLevel(ctx context.Context, level loggers.Level)
SetResponseTimeLogLevel sets the log level for response time logging. Default is InfoLevel. Must be called during initialization, before the server starts. Not safe for concurrent use.
-## func [TraceIdInterceptor]()
+## func [TraceIdInterceptor]()
```go
func TraceIdInterceptor() grpc.UnaryServerInterceptor
@@ -328,7 +311,7 @@ func TraceIdInterceptor() grpc.UnaryServerInterceptor
TraceIdInterceptor allows injecting trace id from request objects
-## func [UseColdBrewClientInterceptors]()
+## func [UseColdBrewClientInterceptors]()
```go
func UseColdBrewClientInterceptors(ctx context.Context, flag bool)
@@ -337,7 +320,7 @@ func UseColdBrewClientInterceptors(ctx context.Context, flag bool)
UseColdBrewClientInterceptors allows enabling/disabling coldbrew client interceptors. When set to false, the coldbrew client interceptors will not be used. Must be called during initialization, before any RPCs are made. Not safe for concurrent use.
-## func [UseColdBrewServerInterceptors]()
+## func [UseColdBrewServerInterceptors]()
```go
func UseColdBrewServerInterceptors(ctx context.Context, flag bool)
@@ -346,7 +329,7 @@ func UseColdBrewServerInterceptors(ctx context.Context, flag bool)
UseColdBrewServerInterceptors allows enabling/disabling coldbrew server interceptors. When set to false, the coldbrew server interceptors will not be used. Must be called during initialization, before the server starts. Not safe for concurrent use.
-## type [FilterFunc]()
+## type [FilterFunc]()
If it returns false, the given request will not be traced.
diff --git a/interceptors.go b/interceptors.go
index 842bb06..b95db72 100644
--- a/interceptors.go
+++ b/interceptors.go
@@ -12,6 +12,7 @@ import (
"net/http"
"runtime/debug"
"strings"
+ "sync"
"time"
"github.com/afex/hystrix-go/hystrix"
@@ -112,8 +113,10 @@ func UseColdBrewClientInterceptors(ctx context.Context, flag bool) {
useCBClientInterceptors = flag
}
-// DoHTTPtoGRPC allows calling the interceptors when you use the RegisterHandlerServer in grpc-gateway,
-// see example below for reference
+// DoHTTPtoGRPC allows calling the interceptors when you use the RegisterHandlerServer in grpc-gateway.
+// The interceptor chain is cached on first invocation. All interceptor configuration
+// (AddUnaryServerInterceptor, SetFilterFunc, etc.) must be finalized before the first call.
+// See example below for reference
//
// func (s *svc) Echo(ctx context.Context, req *proto.EchoRequest) (*proto.EchoResponse, error) {
// handler := func(ctx context.Context, req interface{}) (interface{}, error) {
@@ -129,10 +132,22 @@ func UseColdBrewClientInterceptors(ctx context.Context, flag bool) {
// func (s *svc) echo(ctx context.Context, req *proto.EchoRequest) (*proto.EchoResponse, error) {
// .... implementation ....
// }
+var (
+ httpToGRPCOnce sync.Once
+ httpToGRPCInterceptor grpc.UnaryServerInterceptor
+)
+
+func getHTTPtoGRPCInterceptor() grpc.UnaryServerInterceptor {
+ httpToGRPCOnce.Do(func() {
+ httpToGRPCInterceptor = grpc_middleware.ChainUnaryServer(DefaultInterceptors()...)
+ })
+ return httpToGRPCInterceptor
+}
+
func DoHTTPtoGRPC(ctx context.Context, svr interface{}, handler func(ctx context.Context, req interface{}) (interface{}, error), in interface{}) (interface{}, error) {
method, ok := runtime.RPCMethod(ctx)
if ok {
- interceptor := grpc_middleware.ChainUnaryServer(DefaultInterceptors()...)
+ interceptor := getHTTPtoGRPCInterceptor()
info := &grpc.UnaryServerInfo{
Server: svr,
FullMethod: method,