From eef9cc8ca929dc289cce2fc0a91c3a2c8357e299 Mon Sep 17 00:00:00 2001 From: "vforfreedom96@gmail.com" Date: Tue, 23 Jul 2024 01:06:29 +0800 Subject: [PATCH] feat:add protomessage field validator --- gateway/serialization.go | 3 +- go.mod | 2 +- go.sum | 2 + internal/middleware/vaildator.go | 14 +- internal/middleware/vaildator_test.go | 120 ++-- testdata/desc.pb | Bin 11893 -> 14056 bytes testdata/gateway.json | 894 +++++++++++++++++--------- testdata/helloworld.pb | Bin 12161 -> 12234 bytes testdata/helloworld.proto | 102 +++ 9 files changed, 781 insertions(+), 356 deletions(-) create mode 100644 testdata/helloworld.proto diff --git a/gateway/serialization.go b/gateway/serialization.go index 9acd5af..b05e164 100644 --- a/gateway/serialization.go +++ b/gateway/serialization.go @@ -3,7 +3,6 @@ package gateway import ( "fmt" "io" - "log" _ "github.com/begonia-org/go-sdk/api/app/v1" _ "github.com/begonia-org/go-sdk/api/endpoint/v1" @@ -201,7 +200,7 @@ func (m *JSONMarshaler) Marshal(v interface{}) ([]byte, error) { } if response, ok := v.(*dynamicpb.Message); ok { - log.Println("实际类型,", response.Type().Descriptor().Name()) + // log.Println("实际类型,", response.Type().Descriptor().Name()) byteData, err := m.JSONPb.Marshal(response) if err != nil { return nil, status.Errorf(codes.Internal, "marshal_response: %v", err) diff --git a/go.mod b/go.mod index 8525ff3..6ed2055 100644 --- a/go.mod +++ b/go.mod @@ -80,7 +80,7 @@ require ( require ( github.com/agiledragon/gomonkey/v2 v2.11.0 github.com/begonia-org/go-loadbalancer v0.0.0-20240519060752-71ca464f0f1a - github.com/begonia-org/go-sdk v0.0.0-20240722154330-ecc143356037 + github.com/begonia-org/go-sdk v0.0.0-20240722164044-30e4fbeca04c github.com/go-git/go-git/v5 v5.11.0 github.com/go-playground/validator/v10 v10.19.0 github.com/gorilla/websocket v1.5.0 diff --git a/go.sum b/go.sum index 0f2d97e..19c9235 100644 --- a/go.sum +++ b/go.sum @@ -27,6 +27,8 @@ github.com/begonia-org/go-sdk v0.0.0-20240714083941-00e95e667477 h1:8LhQbM+Y51bs github.com/begonia-org/go-sdk v0.0.0-20240714083941-00e95e667477/go.mod h1:2mHpFudwolu6RHF18EX+lnFYyTNnwDxBD6JcfRcahz8= github.com/begonia-org/go-sdk v0.0.0-20240722154330-ecc143356037 h1:6k1LVmKwSf/4Mm1SuB/RRRYN9VtTuHvwDadGjq9MiEE= github.com/begonia-org/go-sdk v0.0.0-20240722154330-ecc143356037/go.mod h1:2mHpFudwolu6RHF18EX+lnFYyTNnwDxBD6JcfRcahz8= +github.com/begonia-org/go-sdk v0.0.0-20240722164044-30e4fbeca04c h1:Al780pVPkCmZ9n+NrjFZbTVzbKrd82dVMVfKn+twacQ= +github.com/begonia-org/go-sdk v0.0.0-20240722164044-30e4fbeca04c/go.mod h1:2mHpFudwolu6RHF18EX+lnFYyTNnwDxBD6JcfRcahz8= github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= diff --git a/internal/middleware/vaildator.go b/internal/middleware/vaildator.go index 93e87d5..0f53057 100644 --- a/internal/middleware/vaildator.go +++ b/internal/middleware/vaildator.go @@ -168,7 +168,7 @@ func (p *ParamsValidatorImpl) getValidatePath(message protoreflect.ProtoMessage, // FiltersFields 从FieldMask中获取过滤字段,获取待验证字段 // required 字段优先级高于FieldMask -func (p *ParamsValidatorImpl) FiltersMessageFields(v interface{}, parent string) []string { +func (p *ParamsValidatorImpl) FiltersMessageFields(v interface{}) []string { // fieldsMap := getFieldNamesFromJSONTags(v) requiredFields := make([]string, 0) maskFields := make([]string, 0) @@ -182,7 +182,7 @@ func (p *ParamsValidatorImpl) FiltersMessageFields(v interface{}, parent string) // require 字段必须校验 if p.isRequiredField(field) { // log.Printf("required field:%s", field.JSONName()) - requiredFields = append(requiredFields, p.getValidatePath(message, field.JSONName(), parent)...) + requiredFields = append(requiredFields, p.getValidatePath(message, field.JSONName(), "")...) } // 检查字段是否是FieldMask类型 @@ -198,11 +198,11 @@ func (p *ParamsValidatorImpl) FiltersMessageFields(v interface{}, parent string) paths = append(paths, mask.Paths...) for _, path := range paths { maskField := strcase.ToCamel(path) - if parent != "" { - maskField = fmt.Sprintf("%s.%s", parent, strcase.ToCamel(path)) - } + // if parent != "" { + // maskField = fmt.Sprintf("%s.%s", parent, strcase.ToCamel(path)) + // } maskFields = append(maskFields, maskField) - maskFields = append(maskFields, p.getValidatePath(message, path, parent)...) + maskFields = append(maskFields, p.getValidatePath(message, path, "")...) } } } @@ -274,7 +274,7 @@ func (p *ParamsValidatorImpl) ValidateParams(v interface{}) error { // p.validate.Struct() var err error if message, ok := v.(proto.Message); ok { - filters := p.FiltersMessageFields(v, "") + filters := p.FiltersMessageFields(v) duplicateFilters := make([]string, 0) fieldsSet := make(map[string]struct{}) for _, f := range filters { diff --git a/internal/middleware/vaildator_test.go b/internal/middleware/vaildator_test.go index 0e7a2ff..bf3cc84 100644 --- a/internal/middleware/vaildator_test.go +++ b/internal/middleware/vaildator_test.go @@ -106,63 +106,64 @@ func TestValidateDynamicProtoMessage(t *testing.T) { } func TestValidateProtoMessage(t *testing.T) { - c.Convey("test validator unary interceptor", t, func() { - validator := middleware.NewParamsValidator() - - validator.SetPriority(1) - c.So(validator.Priority(), c.ShouldEqual, 1) - c.So(validator.Name(), c.ShouldEqual, "ParamsValidator") - req := &hello.HelloRequestWithValidator{ - Name: "test", - Msg: "test", - Age: 19, - Age2: 19, - FloatNum: 1.1, - BoolData: true, - BytesData: []byte("test"), - ExEnum: hello.ExampleEnum_EX_RUNNING, - ExEnums: []hello.ExampleEnum{ - hello.ExampleEnum_EX_RUNNING, - }, - EnumMap: map[string]hello.ExampleEnum{ - "test": hello.ExampleEnum_EX_RUNNING, - }, - EnumMap2: map[string]hello.ExampleEnum{ - "test": hello.ExampleEnum_EX_UNKNOWN, - }, - Strs: []string{"test"}, - Sub: &hello.HelloSubRequest{ - SubMsg: "test", + req := &hello.HelloRequestWithValidator{ + Name: "test", + Msg: "test", + Age: 19, + Age2: 19, + FloatNum: 1.1, + BoolData: true, + BytesData: []byte("test"), + ExEnum: hello.ExampleEnum_EX_RUNNING, + ExEnums: []hello.ExampleEnum{ + hello.ExampleEnum_EX_RUNNING, + }, + EnumMap: map[string]hello.ExampleEnum{ + "test": hello.ExampleEnum_EX_RUNNING, + }, + EnumMap2: map[string]hello.ExampleEnum{ + "test": hello.ExampleEnum_EX_UNKNOWN, + }, + Strs: []string{"test"}, + Sub: &hello.HelloSubRequest{ + SubMsg: "test", + SubAge: 19, + SubName: "test", + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"sub_name", "sub_msg"}}, + }, + Subs: []*hello.HelloSubRequest{ + { SubAge: 19, SubName: "test", + SubMsg: "test", UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"sub_name", "sub_msg"}}, }, - Subs: []*hello.HelloSubRequest{ - { - SubAge: 19, - SubName: "test", - SubMsg: "test", - UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"sub_name", "sub_msg"}}, - }, - { - SubName: "test", - SubAge: 19, - SubMsg: "test", - UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"sub_msg"}}, - }, - }, - SubMap: map[string]*hello.HelloSubRequest{ - "TEST1": { - SubName: "test", - SubAge: 19, - UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"sub_name", "sub_age"}}, - }, + { + SubName: "test", + SubAge: 19, + SubMsg: "test", + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"sub_msg"}}, }, - SubMap2: map[string]string{ - "TEST1": "test", + }, + SubMap: map[string]*hello.HelloSubRequest{ + "TEST1": { + SubName: "test", + SubAge: 19, + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"sub_name", "sub_age"}}, }, - UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"name", "msg", "sub", "subs", "sub_map", "sub_map2"}}, - } + }, + SubMap2: map[string]string{ + "TEST1": "test", + }, + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"name", "msg", "sub", "subs", "sub_map", "sub_map2"}}, + } + c.Convey("test validator unary interceptor", t, func() { + validator := middleware.NewParamsValidator() + + validator.SetPriority(1) + c.So(validator.Priority(), c.ShouldEqual, 1) + c.So(validator.Name(), c.ShouldEqual, "ParamsValidator") + _, err := validator.UnaryInterceptor(context.Background(), req, &grpc.UnaryServerInfo{}, func(ctx context.Context, req interface{}) (interface{}, error) { return nil, nil }) @@ -273,6 +274,13 @@ func TestValidateProtoMessage(t *testing.T) { }) c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, "Sub2") + req16 := tiga.DeepCopy(req).(*hello.HelloRequestWithValidator) + req16.Sub = nil + _, err = validator.UnaryInterceptor(context.Background(), req16, &grpc.UnaryServerInfo{}, func(ctx context.Context, req interface{}) (interface{}, error) { + return nil, nil + }) + c.So(err, c.ShouldNotBeNil) + c.So(err.Error(), c.ShouldContainSubstring, "Sub") st := struct { Name string `validate:"required"` @@ -283,6 +291,15 @@ func TestValidateProtoMessage(t *testing.T) { c.So(err, c.ShouldNotBeNil) c.So(err.Error(), c.ShouldContainSubstring, "params is not a proto.Message") + }) + c.Convey("test NewStructFromProtobuf",t,func(){ + validate:=validator.New() + vd:=middleware.NewProtobufValidate(validate) + v:=vd.NewStructFromProtobuf(tiga.DeepCopy(req).(*hello.HelloRequestWithValidator),common.E_Validate) + err:=validate.Struct(v) + c.So(err,c.ShouldBeNil) + + }) } func TestValidator(t *testing.T) { @@ -326,6 +343,7 @@ func TestValidatorStreamClientInterceptor(t *testing.T) { return nil, nil }) c.So(err, c.ShouldBeNil) + }) } diff --git a/testdata/desc.pb b/testdata/desc.pb index 59f32fdd0bcffa3e2ac2e867d5e328a2e8597158..5d85c17d7984089b430e50f1915cc28f1d75869f 100644 GIT binary patch delta 1973 zcmbVN%Wm676b&iKvaV!Vow_!oI<~|VvFsG2t#lKk8!J`f0*+&h7jBCd1|^PUA*9KW z^g}2L0tJF(*@8enAYYI`=(7J%pubQQ-E>)?i!L$`QKA*t2)yFVeVlXd%pKl;zx~@D z{BrxX{6^|j2M_Pum6raJpwe}mu0?d$a{{Mz($PCTVws1w;XnO(S=p^Z?jbWgrh7C8 z8P^Dod_}6HYB?-6jpq`4*mi790BJE$qc}?3W7vDrH}&ZMm6akVVEAt9KS_#ewe`WX zl?A!_VirnA#Il?-$FodSFjA6q=src$hppA%1{L zkh1+Q6)#coY>5!0+m1;TnVK?~uT`40%~V{Ob!^xoD~Ho;t!@Ggvs|l>6v)~n^nIgC zhIDk#w~X?gRO!}qy>yY*6qDRD0=j-#@_#Ct`5st&uH)$v~&kftP$m1bX z$W>e>VzO?u2)T~s7{TH3iLIpQfk=34KuZ9^YZ`%}6scRr2@A_^^#gLq-D&DB;Bai= zZpX2NJ44;mIM<2|=q_XocJIm*^%UzLC5vrRIa|z$MGX1`X6V`Q!xC^=+KefD(a7|M zo!&VyMa(n>o}z+B7F2<}Ki(=i8c@PX6C)B4_v!)!Xv{3WXhbR$I7}Rrr$JfFY#}j+ zM)WxpMw(d*7O3QWT}jrN>^XcP8m)=GouSBACGn2dAkChZf+|v)Mwg?iJRh>hi@ANR z0=dzNq8wzlc6Oc|ly0DDNPp4X{kkO8f1QHtBae`Pc<4Kr-Z%PO8oE?%`I6>Tmw)`@ z&q%(hhI6{%_Vm*Yorn(AUB?eLr8RU2`56BZ39do0#3>XsKgsYtdt^VLEk+QE3h>^8 zYcSkE=dciq+$Y{C@%DQrX`Yhf_Z1u_UaY#x72ihHNyR?L)_tGoLj1af&R{O4en9^Q z$H9K!5yQTsjGM`xqCXS%PD1flQEQx9Rc}pFw>h@%b8vbuH3|9fLCkzWTE5eMdae86 zl)JKuDwCYUa?fJ$nndgU3JNi6!!i44E*>hhf3)o&aG5pw?bC&Dk=HV>zSCMQmPcSF z#^Dp-;(;ZH!llita)L!vo)k{lNV%^EbfPqR@Nv)4x}MwChOO-<&c89sU(Nv=XYmN! oh&Hw5N|)ZsnbFseM&s_4oZ8+wXif3yd2i6EZped|tN*0m0-I5O^Z)<= delta 33 pcmaEn`!#0sdZu*6&8PJZm^L!5XWA^LqRqHjOHG_<^KZkqECBIL4B7wy diff --git a/testdata/gateway.json b/testdata/gateway.json index 14807a4..1cce33a 100644 --- a/testdata/gateway.json +++ b/testdata/gateway.json @@ -1,296 +1,600 @@ { - "/integration.TestService/Body": [ - { - "Pattern": {}, - "Template": { - "Version": 1, - "OpCodes": [ - 2, - 0, - 2, - 1 - ], - "Pool": [ - "test", - "body" - ], - "Verb": "", - "Fields": null, - "Template": "/test/body" - }, - "HttpMethod": "GET", - "FullMethodName": "/integration.TestService/Body", - "HttpUri": "/test/body", - "PathParams": [], - "InName": "TestRequest", - "OutName": "HttpBody", - "IsClientStream": false, - "IsServerStream": false, - "Pkg": "integration", - "InPkg": "integration", - "OutPkg": "google.api" - } - ], - "/integration.TestService/Custom": [ - { - "Pattern": {}, - "Template": { - "Version": 1, - "OpCodes": [ - 2, - 0, - 2, - 1 - ], - "Pool": [ - "test", - "custom" - ], - "Verb": "", - "Fields": null, - "Template": "/test/custom" - }, - "HttpMethod": "GET", - "FullMethodName": "/integration.TestService/Custom", - "HttpUri": "/test/custom", - "PathParams": [], - "InName": "TestRequest", - "OutName": "TestRequest", - "IsClientStream": false, - "IsServerStream": false, - "Pkg": "integration", - "InPkg": "integration", - "OutPkg": "integration" - } - ], - "/integration.TestService/Delete": [ - { - "Pattern": {}, - "Template": { - "Version": 1, - "OpCodes": [ - 2, - 0, - 2, - 1 - ], - "Pool": [ - "test", - "del" - ], - "Verb": "", - "Fields": null, - "Template": "/test/del" - }, - "HttpMethod": "DELETE", - "FullMethodName": "/integration.TestService/Delete", - "HttpUri": "/test/del", - "PathParams": [], - "InName": "TestRequest", - "OutName": "TestResponse", - "IsClientStream": false, - "IsServerStream": false, - "Pkg": "integration", - "InPkg": "integration", - "OutPkg": "integration" - } - ], - "/integration.TestService/Get": [ - { - "Pattern": {}, - "Template": { - "Version": 1, - "OpCodes": [ - 2, - 0, - 2, - 1 - ], - "Pool": [ - "test", - "get" - ], - "Verb": "", - "Fields": null, - "Template": "/test/get" - }, - "HttpMethod": "GET", - "FullMethodName": "/integration.TestService/Get", - "HttpUri": "/test/get", - "PathParams": [], - "InName": "TestRequest", - "OutName": "TestResponse", - "IsClientStream": false, - "IsServerStream": false, - "Pkg": "integration", - "InPkg": "integration", - "OutPkg": "integration" - } - ], - "/integration.TestService/Patch": [ - { - "Pattern": {}, - "Template": { - "Version": 1, - "OpCodes": [ - 2, - 0, - 2, - 1 - ], - "Pool": [ - "test", - "patch" - ], - "Verb": "", - "Fields": null, - "Template": "/test/patch" - }, - "HttpMethod": "PATCH", - "FullMethodName": "/integration.TestService/Patch", - "HttpUri": "/test/patch", - "PathParams": [], - "InName": "TestRequest", - "OutName": "TestResponse", - "IsClientStream": false, - "IsServerStream": false, - "Pkg": "integration", - "InPkg": "integration", - "OutPkg": "integration" - } - ], - "/integration.TestService/Post": [ - { - "Pattern": {}, - "Template": { - "Version": 1, - "OpCodes": [ - 2, - 0, - 2, - 1 - ], - "Pool": [ - "test", - "post" - ], - "Verb": "", - "Fields": null, - "Template": "/test/post" - }, - "HttpMethod": "POST", - "FullMethodName": "/integration.TestService/Post", - "HttpUri": "/test/post", - "PathParams": [], - "InName": "TestRequest", - "OutName": "TestResponse", - "IsClientStream": false, - "IsServerStream": false, - "Pkg": "integration", - "InPkg": "integration", - "OutPkg": "integration" - } - ], - "/integration.TestService/Put": [ - { - "Pattern": {}, - "Template": { - "Version": 1, - "OpCodes": [ - 2, - 0, - 2, - 1 - ], - "Pool": [ - "test", - "put" - ], - "Verb": "", - "Fields": null, - "Template": "/test/put" - }, - "HttpMethod": "PUT", - "FullMethodName": "/integration.TestService/Put", - "HttpUri": "/test/put", - "PathParams": [], - "InName": "TestRequest", - "OutName": "TestResponse", - "IsClientStream": false, - "IsServerStream": false, - "Pkg": "integration", - "InPkg": "integration", - "OutPkg": "integration" - } - ], - "/integration.TestServiceWithoutOptions/Get": [ - { - "Pattern": {}, - "Template": { - "Version": 1, - "OpCodes": [ - 2, - 0, - 2, - 1, - 2, - 2 - ], - "Pool": [ - "test", - "v2", - "get" - ], - "Verb": "", - "Fields": null, - "Template": "/test/v2/get" - }, - "HttpMethod": "GET", - "FullMethodName": "/integration.TestServiceWithoutOptions/Get", - "HttpUri": "/test/v2/get", - "PathParams": [], - "InName": "TestRequest", - "OutName": "TestResponse", - "IsClientStream": false, - "IsServerStream": false, - "Pkg": "integration", - "InPkg": "integration", - "OutPkg": "integration" - } - ], - "/integration.TestServiceWithoutOptions/Post": [ - { - "Pattern": {}, - "Template": { - "Version": 1, - "OpCodes": [ - 2, - 0, - 2, - 1, - 2, - 2 - ], - "Pool": [ - "test", - "v2", - "post" - ], - "Verb": "", - "Fields": null, - "Template": "/test/v2/post" - }, - "HttpMethod": "POST", - "FullMethodName": "/integration.TestServiceWithoutOptions/Post", - "HttpUri": "/test/v2/post", - "PathParams": [], - "InName": "TestRequest", - "OutName": "TestResponse", - "IsClientStream": false, - "IsServerStream": false, - "Pkg": "integration", - "InPkg": "integration", - "OutPkg": "integration" - } - ] -} \ No newline at end of file + "/helloworld.Greeter/SayHello": [ + { + "FullMethodName": "/helloworld.Greeter/SayHello", + "HttpMethod": "POST", + "HttpUri": "/api/v1/example/post", + "InName": "HelloRequest", + "InPkg": "helloworld", + "IsClientStream": false, + "IsServerStream": false, + "OutName": "HelloReply", + "OutPkg": "helloworld", + "PathParams": [], + "Pattern": {}, + "Pkg": "helloworld", + "Template": { + "Fields": null, + "OpCodes": [ + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3 + ], + "Pool": [ + "api", + "v1", + "example", + "post" + ], + "Template": "/api/v1/example/post", + "Verb": "", + "Version": 1 + } + } + ], + "/helloworld.Greeter/SayHelloBody": [ + { + "FullMethodName": "/helloworld.Greeter/SayHelloBody", + "HttpMethod": "POST", + "HttpUri": "/api/v1/example/body", + "InName": "HttpBody", + "InPkg": "google.api", + "IsClientStream": false, + "IsServerStream": false, + "OutName": "HttpBody", + "OutPkg": "google.api", + "PathParams": [], + "Pattern": {}, + "Pkg": "helloworld", + "Template": { + "Fields": null, + "OpCodes": [ + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3 + ], + "Pool": [ + "api", + "v1", + "example", + "body" + ], + "Template": "/api/v1/example/body", + "Verb": "", + "Version": 1 + } + } + ], + "/helloworld.Greeter/SayHelloClientStream": [ + { + "FullMethodName": "/helloworld.Greeter/SayHelloClientStream", + "HttpMethod": "POST", + "HttpUri": "/api/v1/example/client/stream", + "InName": "HelloRequest", + "InPkg": "helloworld", + "IsClientStream": true, + "IsServerStream": false, + "OutName": "RepeatedReply", + "OutPkg": "helloworld", + "PathParams": [], + "Pattern": {}, + "Pkg": "helloworld", + "Template": { + "Fields": null, + "OpCodes": [ + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4 + ], + "Pool": [ + "api", + "v1", + "example", + "client", + "stream" + ], + "Template": "/api/v1/example/client/stream", + "Verb": "", + "Version": 1 + } + } + ], + "/helloworld.Greeter/SayHelloError": [ + { + "FullMethodName": "/helloworld.Greeter/SayHelloError", + "HttpMethod": "GET", + "HttpUri": "/api/v1/example/error/test", + "InName": "ErrorRequest", + "InPkg": "helloworld", + "IsClientStream": false, + "IsServerStream": false, + "OutName": "HelloReply", + "OutPkg": "helloworld", + "PathParams": [], + "Pattern": {}, + "Pkg": "helloworld", + "Template": { + "Fields": null, + "OpCodes": [ + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4 + ], + "Pool": [ + "api", + "v1", + "example", + "error", + "test" + ], + "Template": "/api/v1/example/error/test", + "Verb": "", + "Version": 1 + } + } + ], + "/helloworld.Greeter/SayHelloGet": [ + { + "FullMethodName": "/helloworld.Greeter/SayHelloGet", + "HttpMethod": "GET", + "HttpUri": "/api/v1/example/{name}", + "InName": "HelloRequest", + "InPkg": "helloworld", + "IsClientStream": false, + "IsServerStream": false, + "OutName": "HelloReply", + "OutPkg": "helloworld", + "PathParams": [ + "name" + ], + "Pattern": {}, + "Pkg": "helloworld", + "Template": { + "Fields": [ + "name" + ], + "OpCodes": [ + 2, + 0, + 2, + 1, + 2, + 2, + 1, + 0, + 4, + 1, + 5, + 3 + ], + "Pool": [ + "api", + "v1", + "example", + "name" + ], + "Template": "/api/v1/example/{name}", + "Verb": "", + "Version": 1 + } + } + ], + "/helloworld.Greeter/SayHelloRPC": [], + "/helloworld.Greeter/SayHelloServerSideEvent": [ + { + "FullMethodName": "/helloworld.Greeter/SayHelloServerSideEvent", + "HttpMethod": "GET", + "HttpUri": "/api/v1/example/server/sse/{name}", + "InName": "HelloRequest", + "InPkg": "helloworld", + "IsClientStream": false, + "IsServerStream": true, + "OutName": "HelloReply", + "OutPkg": "helloworld", + "PathParams": [ + "name" + ], + "Pattern": {}, + "Pkg": "helloworld", + "Template": { + "Fields": [ + "name" + ], + "OpCodes": [ + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4, + 1, + 0, + 4, + 1, + 5, + 5 + ], + "Pool": [ + "api", + "v1", + "example", + "server", + "sse", + "name" + ], + "Template": "/api/v1/example/server/sse/{name}", + "Verb": "", + "Version": 1 + } + } + ], + "/helloworld.Greeter/SayHelloWebsocket": [ + { + "FullMethodName": "/helloworld.Greeter/SayHelloWebsocket", + "HttpMethod": "GET", + "HttpUri": "/api/v1/example/server/websocket", + "InName": "HelloRequest", + "InPkg": "helloworld", + "IsClientStream": true, + "IsServerStream": true, + "OutName": "HelloReply", + "OutPkg": "helloworld", + "PathParams": [], + "Pattern": {}, + "Pkg": "helloworld", + "Template": { + "Fields": null, + "OpCodes": [ + 2, + 0, + 2, + 1, + 2, + 2, + 2, + 3, + 2, + 4 + ], + "Pool": [ + "api", + "v1", + "example", + "server", + "websocket" + ], + "Template": "/api/v1/example/server/websocket", + "Verb": "", + "Version": 1 + } + } + ], + "/integration.TestService/Body": [ + { + "FullMethodName": "/integration.TestService/Body", + "HttpMethod": "GET", + "HttpUri": "/test/body", + "InName": "TestRequest", + "InPkg": "integration", + "IsClientStream": false, + "IsServerStream": false, + "OutName": "HttpBody", + "OutPkg": "google.api", + "PathParams": [], + "Pattern": {}, + "Pkg": "integration", + "Template": { + "Fields": null, + "OpCodes": [ + 2, + 0, + 2, + 1 + ], + "Pool": [ + "test", + "body" + ], + "Template": "/test/body", + "Verb": "", + "Version": 1 + } + } + ], + "/integration.TestService/Custom": [ + { + "FullMethodName": "/integration.TestService/Custom", + "HttpMethod": "GET", + "HttpUri": "/test/custom", + "InName": "TestRequest", + "InPkg": "integration", + "IsClientStream": false, + "IsServerStream": false, + "OutName": "TestRequest", + "OutPkg": "integration", + "PathParams": [], + "Pattern": {}, + "Pkg": "integration", + "Template": { + "Fields": null, + "OpCodes": [ + 2, + 0, + 2, + 1 + ], + "Pool": [ + "test", + "custom" + ], + "Template": "/test/custom", + "Verb": "", + "Version": 1 + }, + "http_response": "begonia.org.sdk.common.HttpResponse" + } + ], + "/integration.TestService/Delete": [ + { + "FullMethodName": "/integration.TestService/Delete", + "HttpMethod": "DELETE", + "HttpUri": "/test/del", + "InName": "TestRequest", + "InPkg": "integration", + "IsClientStream": false, + "IsServerStream": false, + "OutName": "TestResponse", + "OutPkg": "integration", + "PathParams": [], + "Pattern": {}, + "Pkg": "integration", + "Template": { + "Fields": null, + "OpCodes": [ + 2, + 0, + 2, + 1 + ], + "Pool": [ + "test", + "del" + ], + "Template": "/test/del", + "Verb": "", + "Version": 1 + }, + "http_response": "begonia.org.sdk.common.HttpResponse" + } + ], + "/integration.TestService/Get": [ + { + "FullMethodName": "/integration.TestService/Get", + "HttpMethod": "GET", + "HttpUri": "/test/get", + "InName": "TestRequest", + "InPkg": "integration", + "IsClientStream": false, + "IsServerStream": false, + "OutName": "TestResponse", + "OutPkg": "integration", + "PathParams": [], + "Pattern": {}, + "Pkg": "integration", + "Template": { + "Fields": null, + "OpCodes": [ + 2, + 0, + 2, + 1 + ], + "Pool": [ + "test", + "get" + ], + "Template": "/test/get", + "Verb": "", + "Version": 1 + }, + "http_response": "begonia.org.sdk.common.HttpResponse" + } + ], + "/integration.TestService/Patch": [ + { + "FullMethodName": "/integration.TestService/Patch", + "HttpMethod": "PATCH", + "HttpUri": "/test/patch", + "InName": "TestRequest", + "InPkg": "integration", + "IsClientStream": false, + "IsServerStream": false, + "OutName": "TestResponse", + "OutPkg": "integration", + "PathParams": [], + "Pattern": {}, + "Pkg": "integration", + "Template": { + "Fields": null, + "OpCodes": [ + 2, + 0, + 2, + 1 + ], + "Pool": [ + "test", + "patch" + ], + "Template": "/test/patch", + "Verb": "", + "Version": 1 + }, + "http_response": "begonia.org.sdk.common.HttpResponse" + } + ], + "/integration.TestService/Post": [ + { + "FullMethodName": "/integration.TestService/Post", + "HttpMethod": "POST", + "HttpUri": "/test/post", + "InName": "TestRequest", + "InPkg": "integration", + "IsClientStream": false, + "IsServerStream": false, + "OutName": "TestResponse", + "OutPkg": "integration", + "PathParams": [], + "Pattern": {}, + "Pkg": "integration", + "Template": { + "Fields": null, + "OpCodes": [ + 2, + 0, + 2, + 1 + ], + "Pool": [ + "test", + "post" + ], + "Template": "/test/post", + "Verb": "", + "Version": 1 + }, + "http_response": "begonia.org.sdk.common.HttpResponse" + } + ], + "/integration.TestService/Put": [ + { + "FullMethodName": "/integration.TestService/Put", + "HttpMethod": "PUT", + "HttpUri": "/test/put", + "InName": "TestRequest", + "InPkg": "integration", + "IsClientStream": false, + "IsServerStream": false, + "OutName": "TestResponse", + "OutPkg": "integration", + "PathParams": [], + "Pattern": {}, + "Pkg": "integration", + "Template": { + "Fields": null, + "OpCodes": [ + 2, + 0, + 2, + 1 + ], + "Pool": [ + "test", + "put" + ], + "Template": "/test/put", + "Verb": "", + "Version": 1 + }, + "http_response": "begonia.org.sdk.common.HttpResponse" + } + ], + "/integration.TestServiceWithoutOptions/Get": [ + { + "FullMethodName": "/integration.TestServiceWithoutOptions/Get", + "HttpMethod": "GET", + "HttpUri": "/test/v2/get", + "InName": "TestRequest", + "InPkg": "integration", + "IsClientStream": false, + "IsServerStream": false, + "OutName": "TestResponse", + "OutPkg": "integration", + "PathParams": [], + "Pattern": {}, + "Pkg": "integration", + "Template": { + "Fields": null, + "OpCodes": [ + 2, + 0, + 2, + 1, + 2, + 2 + ], + "Pool": [ + "test", + "v2", + "get" + ], + "Template": "/test/v2/get", + "Verb": "", + "Version": 1 + } + } + ], + "/integration.TestServiceWithoutOptions/Post": [ + { + "FullMethodName": "/integration.TestServiceWithoutOptions/Post", + "HttpMethod": "POST", + "HttpUri": "/test/v2/post", + "InName": "TestRequest", + "InPkg": "integration", + "IsClientStream": false, + "IsServerStream": false, + "OutName": "TestResponse", + "OutPkg": "integration", + "PathParams": [], + "Pattern": {}, + "Pkg": "integration", + "Template": { + "Fields": null, + "OpCodes": [ + 2, + 0, + 2, + 1, + 2, + 2 + ], + "Pool": [ + "test", + "v2", + "post" + ], + "Template": "/test/v2/post", + "Verb": "", + "Version": 1 + } + } + ] +} diff --git a/testdata/helloworld.pb b/testdata/helloworld.pb index 82797fb1c310292ba49907ecf36de5827c3eb45d..54336ca1e9e632989f3b3062e45038364316d2e0 100644 GIT binary patch delta 154 zcmZpSKNY`W0~6!p%^R8i@i2Bz-oSrT%ZN*`IJKxOGdVTBxTGjGF*h?WU4l)4QG>&Z zH7zlxI5kKBD!+N7K%Y2MJO5@!jl0ZDTiGTn=$ztndNzra#9vCF?;xgC$SY2<(K3e0|2sT BH4*>- delta 127 zcmX>V-x$AP0~6!J%^R8i@i2By-oSrT!+=YmIJKxOwJ5&0q$o8pH#09?f=z)@gTsn7 zEitD!HHaS~y?L`hpE%P2zRk`WcbSA*1f(Zhd)~)QZI1 cf}B+S#DYxyGQ&ko%pN}BNo)m0`6c