数据校验
简介
通过 wrapper 的特性,我们可以对 Client
的输出和对 Server
输入的数据进行合法性校验。
实现
package main
import (
"context"
"fmt"
"time"
pb "github.com/vine-io/examples/wrapper/pb"
"github.com/vine-io/vine"
"github.com/vine-io/vine/core/client"
"github.com/vine-io/vine/core/client/grpc"
"github.com/vine-io/vine/core/registry"
"github.com/vine-io/vine/core/server"
verrs "github.com/vine-io/vine/lib/errors"
log "github.com/vine-io/vine/lib/logger"
"github.com/vine-io/vine/lib/trace/memory"
"github.com/vine-io/vine/util/wrapper"
)
type hello struct{}
func (h hello) Echo(ctx context.Context, request *pb.Request, response *pb.Response) error {
response.Result = request.Name
return nil
}
func main() {
s := vine.NewService(
vine.Name("helloworld"),
vine.WrapHandler(HandlerValidatorWrapper()),
)
s.Init()
pb.RegisterHelloHandler(s.Server(), &hello{})
go func() {
time.Sleep(time.Second)
cli := grpc.NewClient(client.WrapCall(CallValidatorWrapper()))
cli = wrapper.TraceCall(s.Name(), memory.NewTracer(), cli)
cc := pb.NewHelloService(s.Name(), cli)
rsp, err := cc.Echo(context.TODO(), &pb.Request{""})
if err != nil {
log.Fatal(err)
}
fmt.Println(rsp)
}()
if err := s.Run(); err != nil {
log.Fatal(err)
}
}
type Validator interface {
Validate() error
}
func CallValidatorWrapper() client.CallWrapper {
return func(fn client.CallFunc) client.CallFunc {
return func(ctx context.Context, node *registry.Node, req client.Request, rsp interface{}, opts client.CallOptions) error {
if v, ok := req.Body().(Validator); ok {
if err := v.Validate(); err != nil {
return verrs.BadRequest(req.Service(), err.Error())
}
}
return fn(ctx, node, req, rsp, opts)
}
}
}
func HandlerValidatorWrapper() server.HandlerWrapper {
return func(fn server.HandlerFunc) server.HandlerFunc {
return func(ctx context.Context, req server.Request, rsp interface{}) error {
if v, ok := req.Body().(Validator); ok {
if err := v.Validate(); err != nil {
return verrs.BadRequest(req.Service(), err.Error())
}
}
return fn(ctx, req, rsp)
}
}
}
最后修改 September 8, 2021: validator (932c7ea)