From cf1208304ae9f0612e6c211703515e42b8127b68 Mon Sep 17 00:00:00 2001 From: Adphi Date: Fri, 1 Aug 2025 09:54:53 +0200 Subject: [PATCH] chore(deps): remove direct dependency on github.com/grpc-ecosystem/go-grpc-middleware (v1) Signed-off-by: Adphi --- client/client.go | 6 +- example/go.mod | 5 +- example/go.sum | 20 --- go.mod | 2 +- interceptors/chain/chain.go | 200 ++++++++++++++----------- interceptors/chain/chain_test.go | 206 ++++++++++++++++++++++++++ interceptors/chain/interceptor.go | 125 ++++++++++++++++ interceptors/logging/interceptor.go | 10 +- interceptors/recovery/interceptors.go | 2 +- service/interceptors.go | 6 +- service/service.go | 6 +- 11 files changed, 460 insertions(+), 128 deletions(-) mode change 100644 => 100755 interceptors/chain/chain.go create mode 100755 interceptors/chain/chain_test.go create mode 100755 interceptors/chain/interceptor.go diff --git a/client/client.go b/client/client.go index d2aecd5..2d3e53d 100644 --- a/client/client.go +++ b/client/client.go @@ -5,12 +5,12 @@ import ( "fmt" "strings" - grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/resolver" + "go.linka.cloud/grpc-toolkit/interceptors/chain" "go.linka.cloud/grpc-toolkit/registry/noop" ) @@ -37,10 +37,10 @@ func New(opts ...Option) (Client, error) { c.opts.dialOptions = append(c.opts.dialOptions, grpc.WithTransportCredentials(insecure.NewCredentials())) } if len(c.opts.unaryInterceptors) > 0 { - c.opts.dialOptions = append(c.opts.dialOptions, grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(c.opts.unaryInterceptors...))) + c.opts.dialOptions = append(c.opts.dialOptions, grpc.WithUnaryInterceptor(chain.UnaryClient(c.opts.unaryInterceptors...))) } if len(c.opts.streamInterceptors) > 0 { - c.opts.dialOptions = append(c.opts.dialOptions, grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(c.opts.streamInterceptors...))) + c.opts.dialOptions = append(c.opts.dialOptions, grpc.WithStreamInterceptor(chain.StreamClient(c.opts.streamInterceptors...))) } switch { case c.opts.addr == "": diff --git a/example/go.mod b/example/go.mod index 97d6e59..bdf31b2 100644 --- a/example/go.mod +++ b/example/go.mod @@ -18,10 +18,8 @@ require ( github.com/planetscale/vtprotobuf v0.6.1-0.20240917153116-6f2963f01587 github.com/prometheus/client_golang v1.22.0 github.com/spf13/cobra v1.8.1 - github.com/uptrace/opentelemetry-go-extra/otellogrus v0.3.2 go.linka.cloud/grpc-toolkit v0.4.3 go.linka.cloud/protoc-gen-defaults v0.4.0 - go.opentelemetry.io/contrib/bridges/otellogrus v0.11.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 go.opentelemetry.io/otel v1.36.0 go.opentelemetry.io/otel/sdk v1.36.0 @@ -50,7 +48,6 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect - github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jaredfolkins/badactor v1.2.0 // indirect @@ -68,8 +65,10 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/tmc/grpc-websocket-proxy v0.0.0-20220101234140-673ab2c3ae75 // indirect github.com/traefik/grpc-web v0.16.0 // indirect + github.com/uptrace/opentelemetry-go-extra/otellogrus v0.3.2 // indirect github.com/uptrace/opentelemetry-go-extra/otelutil v0.3.2 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect + go.opentelemetry.io/contrib/bridges/otellogrus v0.11.0 // indirect go.opentelemetry.io/contrib/bridges/prometheus v0.61.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.56.0 // indirect go.opentelemetry.io/contrib/instrumentation/runtime v0.61.0 // indirect diff --git a/example/go.sum b/example/go.sum index 4ff89dc..7f94834 100644 --- a/example/go.sum +++ b/example/go.sum @@ -40,7 +40,6 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -130,7 +129,6 @@ github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -193,8 +191,6 @@ github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= -github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 h1:qnpSQwGEnkcRpTqNOIR6bJbR0gAorgP9CSALpRcKoAA= github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1/go.mod h1:lXGCsh6c22WGtjr+qGHj1otzZpV/1kwTMAqkwZsnWRU= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= @@ -224,7 +220,6 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/justinas/alice v1.2.0 h1:+MHSA/vccVCF4Uq37S42jwlkvI2Xzl7zTPCN5BnZNVo= github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= @@ -261,7 +256,6 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs= @@ -344,12 +338,9 @@ github.com/uptrace/opentelemetry-go-extra/otellogrus v0.3.2 h1:H8wwQwTe5sL6x30z7 github.com/uptrace/opentelemetry-go-extra/otellogrus v0.3.2/go.mod h1:/kR4beFhlz2g+V5ik8jW+3PMiMQAPt29y6K64NNY53c= github.com/uptrace/opentelemetry-go-extra/otelutil v0.3.2 h1:3/aHKUq7qaFMWxyQV0W2ryNgg8x8rVeKVA20KJUkfS0= github.com/uptrace/opentelemetry-go-extra/otelutil v0.3.2/go.mod h1:Zit4b8AQXaXvA68+nzmbyDzqiyFRISyw1JiD5JqUBjw= -github.com/uptrace/uptrace-go v1.35.1 h1:ZK+YwrPyZcpC9nJUrFiVogI8pBuPtlTbGyjs8LAhirk= -github.com/uptrace/uptrace-go v1.35.1/go.mod h1:N+XGgxkQP1/6iw8fvbP2PrkbK1adyTutLmMgm3Xw7x8= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.linka.cloud/protoc-gen-defaults v0.4.0 h1:ekcfTTY74AhKBGMF9usz+xkUFxLaPVAu6xmQvwmjbfc= go.linka.cloud/protoc-gen-defaults v0.4.0/go.mod h1:IJcTbM/oraQvdE/mz0vxhoBmJHE+rb4vF2IXJztcadY= @@ -400,14 +391,10 @@ go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKr go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.opentelemetry.io/proto/otlp v1.6.0 h1:jQjP+AQyTf+Fe7OKj/MfkDrmK4MNVtw2NpXsf9fefDI= go.opentelemetry.io/proto/otlp v1.6.0/go.mod h1:cicgGehlFuNdgZkcALOCh3VE6K/u2tAjzlRhDwmVpZc= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= @@ -483,7 +470,6 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -510,7 +496,6 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -555,7 +540,6 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -602,7 +586,6 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -625,11 +608,9 @@ golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -679,7 +660,6 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= diff --git a/go.mod b/go.mod index 61b2522..694060d 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,6 @@ require ( github.com/go-logr/logr v1.4.2 github.com/golang/protobuf v1.5.4 github.com/google/uuid v1.6.0 - github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 @@ -75,6 +74,7 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/gobwas/ws v1.1.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jhump/protoreflect v1.11.0 // indirect diff --git a/interceptors/chain/chain.go b/interceptors/chain/chain.go old mode 100644 new mode 100755 index 138f1f8..158cc88 --- a/interceptors/chain/chain.go +++ b/interceptors/chain/chain.go @@ -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...) + } } diff --git a/interceptors/chain/chain_test.go b/interceptors/chain/chain_test.go new file mode 100755 index 0000000..4d09da8 --- /dev/null +++ b/interceptors/chain/chain_test.go @@ -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 +} diff --git a/interceptors/chain/interceptor.go b/interceptors/chain/interceptor.go new file mode 100755 index 0000000..cc77277 --- /dev/null +++ b/interceptors/chain/interceptor.go @@ -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...) +} diff --git a/interceptors/logging/interceptor.go b/interceptors/logging/interceptor.go index fe6d45d..c6b1f6f 100644 --- a/interceptors/logging/interceptor.go +++ b/interceptors/logging/interceptor.go @@ -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) diff --git a/interceptors/recovery/interceptors.go b/interceptors/recovery/interceptors.go index a302013..6bd3279 100644 --- a/interceptors/recovery/interceptors.go +++ b/interceptors/recovery/interceptors.go @@ -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" diff --git a/service/interceptors.go b/service/interceptors.go index a107a14..00daf74 100644 --- a/service/interceptors.go +++ b/service/interceptors.go @@ -5,11 +5,11 @@ import ( "fmt" "github.com/fullstorydev/grpchan/inprocgrpc" - grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware" "google.golang.org/grpc" insecure2 "google.golang.org/grpc/credentials/insecure" "go.linka.cloud/grpc-toolkit/interceptors" + "go.linka.cloud/grpc-toolkit/interceptors/chain" "go.linka.cloud/grpc-toolkit/interceptors/metadata" ) @@ -34,10 +34,10 @@ func (s *service) wrapCC() grpc.ClientConnInterface { } w := &client{ch: s.inproc, c: c} if len(s.opts.unaryClientInterceptors) != 0 { - w.ui = grpc_middleware.ChainUnaryClient(s.opts.unaryClientInterceptors...) + w.ui = chain.UnaryClient(s.opts.unaryClientInterceptors...) } if len(s.opts.streamClientInterceptors) != 0 { - w.si = grpc_middleware.ChainStreamClient(s.opts.streamClientInterceptors...) + w.si = chain.StreamClient(s.opts.streamClientInterceptors...) } return w } diff --git a/service/service.go b/service/service.go index 93a1cd1..2123a32 100644 --- a/service/service.go +++ b/service/service.go @@ -16,7 +16,6 @@ import ( "github.com/fullstorydev/grpchan/inprocgrpc" "github.com/google/uuid" - grpcmiddleware "github.com/grpc-ecosystem/go-grpc-middleware" "github.com/justinas/alice" "github.com/pires/go-proxyproto" "github.com/rs/cors" @@ -30,6 +29,7 @@ import ( "google.golang.org/grpc/health/grpc_health_v1" greflect "google.golang.org/grpc/reflection" + "go.linka.cloud/grpc-toolkit/interceptors/chain" "go.linka.cloud/grpc-toolkit/internal/injectlogger" "go.linka.cloud/grpc-toolkit/logger" "go.linka.cloud/grpc-toolkit/registry" @@ -128,10 +128,10 @@ func newService(opts ...Option) (*service, error) { return nil, err } - ui := grpcmiddleware.ChainUnaryServer(s.opts.unaryServerInterceptors...) + ui := chain.UnaryServer(s.opts.unaryServerInterceptors...) s.inproc = s.inproc.WithServerUnaryInterceptor(ui) - si := grpcmiddleware.ChainStreamServer(s.opts.streamServerInterceptors...) + si := chain.StreamServer(s.opts.streamServerInterceptors...) s.inproc = s.inproc.WithServerStreamInterceptor(si) gopts := []grpc.ServerOption{