thrift-gen-validator is a thriftgo plugin to generate struct validators.
Users can define validation rule for struct-like(struct/union/exception) in Thrift file, then the generator will generate IsValid() error method for those structs.
for example:
enum MapKey {
A, B, C, D, E, F
}
struct Example {
1: string Message (vt.min_size = "30") // length of Message should be greater than or equal to 30
2: i32 ID (vt.ge = "10000") // ID must be greater than or euqal to 10000
3: list<double> Values (vt.elem.gt = "0.25") // element of Values must be greater than 0.25
4: map<MapKey, string> KeyValues (vt.key.defined_only = "true") // value of KeyValues'key must be defined in MapKey
}
generated method:
func (p *Example) IsValid() error {
if len(p.Message) < int(30) {
return fmt.Errorf("field Message min_len rule failed, current value: %d", len(p.Message))
}
if p.ID < int32(10000) {
return fmt.Errorf("field ID ge rule failed, current value: %v", p.ID)
}
for i := 0; i < len(p.Values); i++ {
_elem := p.Values[i]
if _elem <= float64(0.25) {
return fmt.Errorf("field _elem gt rule failed, current value: %v", _elem)
}
}
for k := range p.KeyValues {
if k.String() == "<UNSET>" {
return fmt.Errorf("field k defined_only rule failed")
}
}
return nil
}
Install
go install github.com/cloudwego/thrift-gen-validator@latest
1: sum of two arguments (integer or float64 or string)
just like + of go
Customized Validation Function
Now you can use parameter func to customize your validation function. Like below: thriftgo -g go -p validator:func=my_func=path_to_template.txt my.thrift my_func is the function name, path_to_template.txt is the path to template file which should be a go template.
Available template variables:
| variable name | meaning | type |
| ————- | ————————————- | —————————————————————- |
| Source | variable name that rule will refer to | string |
| StructLike | ast of current struct/union/exception | *”github.com/cloudwego/thriftgo/generator/golang”.StructLike |
| Function | data of current function | *”github.com/cloudwego/thrift-gen-validator/parser”.ToolFunction |
Example
Kitex Middleware Example
package main
import (
"context"
"fmt"
"log"
"github.com/cloudwego/kitex-examples/kitex_gen/api"
"github.com/cloudwego/kitex-examples/kitex_gen/api/echo"
"github.com/cloudwego/kitex/client"
"github.com/cloudwego/kitex/pkg/endpoint"
"github.com/cloudwego/kitex/server"
)
func ValidatorMW(next endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, args, result interface{}) (err error) {
if gfa, ok := args.(interface{ GetFirstArgument() interface{} }); ok {
req := gfa.GetFirstArgument()
if rv, ok := req.(interface{ IsValid() error }); ok {
if err := rv.IsValid(); err != nil {
return fmt.Errorf("request data is not valid:%w", err)
}
}
}
err = next(ctx, args, result)
if err != nil {
return err
}
if gr, ok := result.(interface{ GetResult() interface{} }); ok {
resp := gr.GetResult()
if rv, ok := resp.(interface{ IsValid() error }); ok {
if err := rv.IsValid(); err != nil {
return fmt.Errorf("response data is not valid:%w", err)
}
}
}
return nil
}
}
// for client
func main() {
cli := echo.MustNewClient("service_name", client.WithMiddleware(ValidatorMW))
resp, err := client.Echo(context.Background(), &api.Request{Message: "my request"})
if err != nil {
log.Println(err.Error())
} else {
log.Println(resp)
}
}
// for server
func main() {
svr := echo.NewServer(new(EchoImpl), server.WithMiddleware(ValidatorMW))
err := svr.Run()
if err != nil {
log.Println(err.Error())
}
}
Customize Validation Function Example
If we have a my.thrift like below:
struct Example {
1: string Message (vt.max_size = "@my_length()")
}
And assumes that we want to limit the max length of Message to 10, we can write a template file my_length.txt like below:
{{- .Source}} := 10 /*my length*/
Then we can use command below to generate a validator file: thriftgo -g go -p validator:func=my_length=my_length.txt my.thrift
{{.Source}} indicates _src which will be used in if len(p.Message) > int(_src) {, so all the thing the function template need to do is assign a value to _src aka {{.Source}}. In the above example, {{- .Source}} := + 10 /*my length*/ will do.
Now let’s see a more complex example. Assumes that we have a my.thrift like below:
{{$arg0 := index .Function.Arguments 0}} is used to get the first argument of the function. {{$reference := $arg0.TypedValue.GetFieldReferenceName "p." .StructLike}} is used to get the reference name of the first argument, for there p.MaxLength.
In some scenarios, we might want to import some extra packages, for example, if we want to get some enviroment variables, we need to import os package which is not in the default import list. In this case, we can add following statement to function template file:
thrift-gen-validator
thrift-gen-validator is a thriftgo plugin to generate struct validators. Users can define validation rule for struct-like(struct/union/exception) in Thrift file, then the generator will generate
IsValid() errormethod for those structs.for example:
generated method:
Install
go install github.com/cloudwego/thrift-gen-validator@latestUsage
Thriftgo
thriftgo -g go -p validator my.thriftKitex
kitex --thrift-plugin validator -service a.b.c my.thriftFeature Matrix
prefix
vt, short for “validation”Numeric(i8/i16/i32/i64/double)
Bool
String/Binary
Enum
Set/List
Map
Struct Field
Struct
Special Value
Field Reference Example
Validation Function
lenof go2+: arguments matching format
fmt.Sprintfof gotime.Now().UnixNano()of go==of go%of go+of goCustomized Validation Function
Now you can use parameter
functo customize your validation function. Like below:thriftgo -g go -p validator:func=my_func=path_to_template.txt my.thriftmy_funcis the function name,path_to_template.txtis the path to template file which should be a go template. Available template variables: | variable name | meaning | type | | ————- | ————————————- | —————————————————————- | | Source | variable name that rule will refer to | string | | StructLike | ast of current struct/union/exception | *”github.com/cloudwego/thriftgo/generator/golang”.StructLike | | Function | data of current function | *”github.com/cloudwego/thrift-gen-validator/parser”.ToolFunction |Example
Kitex Middleware Example
Customize Validation Function Example
If we have a
my.thriftlike below:And assumes that we want to limit the max length of
Messageto 10, we can write a template filemy_length.txtlike below:Then we can use command below to generate a validator file:
thriftgo -g go -p validator:func=my_length=my_length.txt my.thriftWe will get a
IsValid() errorlike below:{{.Source}}indicates_srcwhich will be used inif len(p.Message) > int(_src) {, so all the thing the function template need to do is assign a value to_srcaka{{.Source}}. In the above example,{{- .Source}} := + 10 /*my length*/will do.Now let’s see a more complex example. Assumes that we have a
my.thriftlike below:And assumes that we want to limit the max length of
Messageto the sum of MaxLength and 10, we can write a template filefix_length.txtlike below:Then we can use command below to generate a validator file:
thriftgo -g go -p validator:func=fix_length=fix_length.txt my.thriftWe will get a
IsValid() errorlike below:{{$arg0 := index .Function.Arguments 0}}is used to get the first argument of the function.{{$reference := $arg0.TypedValue.GetFieldReferenceName "p." .StructLike}}is used to get the reference name of the first argument, for therep.MaxLength.In some scenarios, we might want to import some extra packages, for example, if we want to get some enviroment variables, we need to import
ospackage which is not in the default import list. In this case, we can add following statement to function template file:Then we can get a validator go file header like below:
You can go to examples/custom-function to see the complete example. And you can view the generated code in examples/custom-function/gen-go/my.