Skip to content

Commit 0c9d258

Browse files
port to v2 (#418)
1 parent 0df73fc commit 0c9d258

File tree

3 files changed

+61
-22
lines changed

3 files changed

+61
-22
lines changed

interceptors/validator/validator.go

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,40 @@ import (
1111
"google.golang.org/grpc/status"
1212
)
1313

14+
// The validate interface starting with protoc-gen-validate v0.6.0.
15+
// See https://github.com/envoyproxy/protoc-gen-validate/pull/455.
1416
type validator interface {
17+
Validate(all bool) error
18+
}
19+
20+
// The validate interface prior to protoc-gen-validate v0.6.0.
21+
type validatorLegacy interface {
1522
Validate() error
1623
}
1724

25+
// Calls the Validate function on a proto message using either the current or legacy interface if the Validate function
26+
// is present. If validation fails, the error is wrapped with `InvalidArgument` and returned.
27+
func validate(req interface{}) error {
28+
switch v := req.(type) {
29+
case validatorLegacy:
30+
if err := v.Validate(); err != nil {
31+
return status.Error(codes.InvalidArgument, err.Error())
32+
}
33+
case validator:
34+
if err := v.Validate(false); err != nil {
35+
return status.Error(codes.InvalidArgument, err.Error())
36+
}
37+
}
38+
return nil
39+
}
40+
1841
// UnaryServerInterceptor returns a new unary server interceptor that validates incoming messages.
1942
//
2043
// Invalid messages will be rejected with `InvalidArgument` before reaching any userspace handlers.
2144
func UnaryServerInterceptor() grpc.UnaryServerInterceptor {
2245
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
23-
if v, ok := req.(validator); ok {
24-
if err := v.Validate(); err != nil {
25-
return nil, status.Errorf(codes.InvalidArgument, err.Error())
26-
}
46+
if err := validate(req); err != nil {
47+
return nil, err
2748
}
2849
return handler(ctx, req)
2950
}
@@ -34,10 +55,8 @@ func UnaryServerInterceptor() grpc.UnaryServerInterceptor {
3455
// Invalid messages will be rejected with `InvalidArgument` before sending the request to server.
3556
func UnaryClientInterceptor() grpc.UnaryClientInterceptor {
3657
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
37-
if v, ok := req.(validator); ok {
38-
if err := v.Validate(); err != nil {
39-
return status.Errorf(codes.InvalidArgument, err.Error())
40-
}
58+
if err := validate(req); err != nil {
59+
return err
4160
}
4261
return invoker(ctx, method, req, reply, cc, opts...)
4362
}
@@ -64,10 +83,8 @@ func (s *recvWrapper) RecvMsg(m interface{}) error {
6483
if err := s.ServerStream.RecvMsg(m); err != nil {
6584
return err
6685
}
67-
if v, ok := m.(validator); ok {
68-
if err := v.Validate(); err != nil {
69-
return status.Errorf(codes.InvalidArgument, err.Error())
70-
}
86+
if err := validate(m); err != nil {
87+
return err
7188
}
7289
return nil
7390
}

interceptors/validator/validator_test.go

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2016 Michal Witkowski. All Rights Reserved.
22
// See LICENSE for licensing terms.
33

4-
package validator_test
4+
package validator
55

66
import (
77
"io"
@@ -14,16 +14,23 @@ import (
1414
"google.golang.org/grpc/codes"
1515
"google.golang.org/grpc/status"
1616

17-
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/validator"
1817
"github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb"
1918
)
2019

20+
func TestValidateWrapper(t *testing.T) {
21+
assert.NoError(t, validate(testpb.GoodPing))
22+
assert.Error(t, validate(testpb.BadPing))
23+
24+
assert.NoError(t, validate(testpb.GoodPingResponse))
25+
assert.Error(t, validate(testpb.BadPingResponse))
26+
}
27+
2128
func TestValidatorTestSuite(t *testing.T) {
2229
s := &ValidatorTestSuite{
2330
InterceptorTestSuite: &testpb.InterceptorTestSuite{
2431
ServerOpts: []grpc.ServerOption{
25-
grpc.StreamInterceptor(validator.StreamServerInterceptor()),
26-
grpc.UnaryInterceptor(validator.UnaryServerInterceptor()),
32+
grpc.StreamInterceptor(StreamServerInterceptor()),
33+
grpc.UnaryInterceptor(UnaryServerInterceptor()),
2734
},
2835
},
2936
}
@@ -32,7 +39,7 @@ func TestValidatorTestSuite(t *testing.T) {
3239
cs := &ClientValidatorTestSuite{
3340
InterceptorTestSuite: &testpb.InterceptorTestSuite{
3441
ClientOpts: []grpc.DialOption{
35-
grpc.WithUnaryInterceptor(validator.UnaryClientInterceptor()),
42+
grpc.WithUnaryInterceptor(UnaryClientInterceptor()),
3643
},
3744
},
3845
}

testing/testpb/test.manual_validator.pb.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,48 @@
22

33
package testpb
44

5-
import "github.com/pkg/errors"
5+
import (
6+
"math"
67

7-
func (x *PingRequest) Validate() error {
8+
"github.com/pkg/errors"
9+
)
10+
11+
func (x *PingRequest) Validate(bool) error {
812
if x.SleepTimeMs > 10000 {
913
return errors.New("cannot sleep for more than 10s")
1014
}
1115
return nil
1216
}
1317

14-
func (x *PingErrorRequest) Validate() error {
18+
func (x *PingErrorRequest) Validate(bool) error {
1519
if x.SleepTimeMs > 10000 {
1620
return errors.New("cannot sleep for more than 10s")
1721
}
1822
return nil
1923
}
2024

21-
func (x *PingListRequest) Validate() error {
25+
func (x *PingListRequest) Validate(bool) error {
2226
if x.SleepTimeMs > 10000 {
2327
return errors.New("cannot sleep for more than 10s")
2428
}
2529
return nil
2630
}
2731

28-
func (x *PingStreamRequest) Validate() error {
32+
func (x *PingStreamRequest) Validate(bool) error {
2933
if x.SleepTimeMs > 10000 {
3034
return errors.New("cannot sleep for more than 10s")
3135
}
3236
return nil
3337
}
3438

39+
// Implements the legacy validation interface from protoc-gen-validate.
40+
func (x *PingResponse) Validate() error {
41+
if x.Counter > math.MaxInt16 {
42+
return errors.New("ping allocation exceeded")
43+
}
44+
return nil
45+
}
46+
3547
var (
3648
GoodPing = &PingRequest{Value: "something", SleepTimeMs: 9999}
3749
GoodPingError = &PingErrorRequest{Value: "something", SleepTimeMs: 9999}
@@ -42,4 +54,7 @@ var (
4254
BadPingError = &PingErrorRequest{Value: "something", SleepTimeMs: 10001}
4355
BadPingList = &PingListRequest{Value: "something", SleepTimeMs: 10001}
4456
BadPingStream = &PingStreamRequest{Value: "something", SleepTimeMs: 10001}
57+
58+
GoodPingResponse = &PingResponse{Counter: 100}
59+
BadPingResponse = &PingResponse{Counter: math.MaxInt16 + 1}
4560
)

0 commit comments

Comments
 (0)