diff --git a/api/metadata/metadata_http.pb.go b/api/metadata/metadata_http.pb.go index e19b1592b..1005cd506 100644 --- a/api/metadata/metadata_http.pb.go +++ b/api/metadata/metadata_http.pb.go @@ -1,4 +1,6 @@ // Code generated by protoc-gen-go-http. DO NOT EDIT. +// versions: +// protoc-gen-go-http v2.0.0-rc3 package metadata @@ -6,126 +8,102 @@ import ( context "context" middleware "github.com/go-kratos/kratos/v2/middleware" transport "github.com/go-kratos/kratos/v2/transport" - http1 "github.com/go-kratos/kratos/v2/transport/http" + http "github.com/go-kratos/kratos/v2/transport/http" binding "github.com/go-kratos/kratos/v2/transport/http/binding" - mux "github.com/gorilla/mux" - http "net/http" ) // This is a compile-time assertion to ensure that this generated file // is compatible with the kratos package it is being compiled against. -var _ = new(http.Request) var _ = new(context.Context) var _ = new(middleware.Middleware) var _ = new(transport.Transporter) var _ = binding.BindVars -var _ = mux.NewRouter -const _ = http1.SupportPackageIsVersion1 +const _ = http.SupportPackageIsVersion1 -type MetadataHandler interface { +type MetadataHTTPServer interface { GetServiceDesc(context.Context, *GetServiceDescRequest) (*GetServiceDescReply, error) - ListServices(context.Context, *ListServicesRequest) (*ListServicesReply, error) } -func NewMetadataHandler(srv MetadataHandler, opts ...http1.HandleOption) http.Handler { - h := http1.DefaultHandleOptions() - for _, o := range opts { - o(&h) - } - r := mux.NewRouter() +func RegisterMetadataHTTPServer(s *http.Server, srv MetadataHTTPServer) { + r := s.Route("/") + r.GET("/services", _Metadata_ListServices0_HTTP_Handler(srv)) + r.GET("/services/{name}", _Metadata_GetServiceDesc0_HTTP_Handler(srv)) +} - r.HandleFunc("/services", func(w http.ResponseWriter, r *http.Request) { +func _Metadata_ListServices0_HTTP_Handler(srv MetadataHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { var in ListServicesRequest - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return + if err := ctx.Bind(&in); err != nil { + return err } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { + transport.SetOperation(ctx, "/kratos.api.Metadata/ListServices") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { return srv.ListServices(ctx, req.(*ListServicesRequest)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/kratos.api.Metadata/ListServices") - out, err := next(ctx, &in) + }) + out, err := h(ctx, &in) if err != nil { - h.Error(w, r, err) - return + return err } reply := out.(*ListServicesReply) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("GET") + return ctx.Result(200, reply) + } +} - r.HandleFunc("/services/{name}", func(w http.ResponseWriter, r *http.Request) { +func _Metadata_GetServiceDesc0_HTTP_Handler(srv MetadataHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { var in GetServiceDescRequest - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return + if err := ctx.Bind(&in); err != nil { + return err } - - if err := binding.BindVars(mux.Vars(r), &in); err != nil { - h.Error(w, r, err) - return + if err := binding.BindVars(ctx.Vars(), &in); err != nil { + return err } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { + transport.SetOperation(ctx, "/kratos.api.Metadata/GetServiceDesc") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { return srv.GetServiceDesc(ctx, req.(*GetServiceDescRequest)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/kratos.api.Metadata/GetServiceDesc") - out, err := next(ctx, &in) + }) + out, err := h(ctx, &in) if err != nil { - h.Error(w, r, err) - return + return err } reply := out.(*GetServiceDescReply) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("GET") - - return r + return ctx.Result(200, reply) + } } type MetadataHTTPClient interface { - GetServiceDesc(ctx context.Context, req *GetServiceDescRequest, opts ...http1.CallOption) (rsp *GetServiceDescReply, err error) - - ListServices(ctx context.Context, req *ListServicesRequest, opts ...http1.CallOption) (rsp *ListServicesReply, err error) + GetServiceDesc(ctx context.Context, req *GetServiceDescRequest, opts ...http.CallOption) (rsp *GetServiceDescReply, err error) + ListServices(ctx context.Context, req *ListServicesRequest, opts ...http.CallOption) (rsp *ListServicesReply, err error) } type MetadataHTTPClientImpl struct { - cc *http1.Client + cc *http.Client } -func NewMetadataHTTPClient(client *http1.Client) MetadataHTTPClient { +func NewMetadataHTTPClient(client *http.Client) MetadataHTTPClient { return &MetadataHTTPClientImpl{client} } -func (c *MetadataHTTPClientImpl) GetServiceDesc(ctx context.Context, in *GetServiceDescRequest, opts ...http1.CallOption) (*GetServiceDescReply, error) { +func (c *MetadataHTTPClientImpl) GetServiceDesc(ctx context.Context, in *GetServiceDescRequest, opts ...http.CallOption) (*GetServiceDescReply, error) { var out GetServiceDescReply - path := binding.EncodePath("GET", "/services/{name}", in) - opts = append(opts, http1.Method("/kratos.api.Metadata/GetServiceDesc")) - + path := binding.EncodeVars("/services/{name}", in, true) + opts = append(opts, http.Operation("/kratos.api.Metadata/GetServiceDesc")) err := c.cc.Invoke(ctx, "GET", path, nil, &out, opts...) - + if err != nil { + return nil, err + } return &out, err } -func (c *MetadataHTTPClientImpl) ListServices(ctx context.Context, in *ListServicesRequest, opts ...http1.CallOption) (*ListServicesReply, error) { +func (c *MetadataHTTPClientImpl) ListServices(ctx context.Context, in *ListServicesRequest, opts ...http.CallOption) (*ListServicesReply, error) { var out ListServicesReply - path := binding.EncodePath("GET", "/services", in) - opts = append(opts, http1.Method("/kratos.api.Metadata/ListServices")) - + path := binding.EncodeVars("/services", in, true) + opts = append(opts, http.Operation("/kratos.api.Metadata/ListServices")) err := c.cc.Invoke(ctx, "GET", path, nil, &out, opts...) - + if err != nil { + return nil, err + } return &out, err } diff --git a/cmd/protoc-gen-go-errors/errors.go b/cmd/protoc-gen-go-errors/errors.go index 03c7a2dda..3380a8527 100644 --- a/cmd/protoc-gen-go-errors/errors.go +++ b/cmd/protoc-gen-go-errors/errors.go @@ -15,7 +15,13 @@ const ( // generateFile generates a _http.pb.go file containing kratos errors definitions. func generateFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile { - if len(file.Enums) == 0 { + var hasCode bool + for _, enum := range file.Enums { + if code := defaultErrorCode(enum); code > 0 { + hasCode = true + } + } + if len(file.Enums) == 0 || !hasCode { return nil } filename := file.GeneratedFilenamePrefix + "_errors.pb.go" @@ -44,36 +50,37 @@ func generateFileContent(gen *protogen.Plugin, file *protogen.File, g *protogen. } } -func genErrorsReason(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile, enum *protogen.Enum) { +func defaultErrorCode(enum *protogen.Enum) int { defaultCode := proto.GetExtension(enum.Desc.Options(), errors.E_DefaultCode) - code := 0 - if ok := defaultCode.(int32); ok != 0 && ok <= 600 && ok >= 200 { - code = int(ok) - } else { - return + if code, ok := defaultCode.(int32); ok && code > 0 { + return int(code) } + return 0 +} + +func genErrorsReason(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile, enum *protogen.Enum) { var ew errorWrapper + defCode := defaultErrorCode(enum) for _, v := range enum.Values { - eCode := proto.GetExtension(v.Desc.Options(), errors.E_Code) - enumCode := int(eCode.(int32)) - if enumCode == 0 { - enumCode = code + code := int(proto.GetExtension(v.Desc.Options(), errors.E_Code).(int32)) + if code == 0 { + code = defCode } - if enumCode > 600 || enumCode < 200 { - return + if code > 600 || code < 200 { + panic("httpstatus code must be greater than or equal to 200 and less than 600") } err := &errorInfo{ Name: string(enum.Desc.Name()), Value: string(v.Desc.Name()), - CamelValue: Case2Camel(string(v.Desc.Name())), - HttpCode: enumCode, + CamelValue: case2Camel(string(v.Desc.Name())), + HttpCode: code, } ew.Errors = append(ew.Errors, err) } g.P(ew.execute()) } -func Case2Camel(name string) string { +func case2Camel(name string) string { if !strings.Contains(name, "_") { return name } diff --git a/cmd/protoc-gen-go-http/http.go b/cmd/protoc-gen-go-http/http.go index 97148677b..3cdca5a17 100644 --- a/cmd/protoc-gen-go-http/http.go +++ b/cmd/protoc-gen-go-http/http.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "strings" "google.golang.org/genproto/googleapis/api/annotations" @@ -11,8 +12,6 @@ import ( const ( contextPackage = protogen.GoImportPath("context") - httpPackage = protogen.GoImportPath("net/http") - muxPackage = protogen.GoImportPath("github.com/gorilla/mux") middlewarePackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/middleware") transportHTTPPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/transport/http") bindingPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/transport/http/binding") @@ -29,6 +28,8 @@ func generateFile(gen *protogen.Plugin, file *protogen.File) *protogen.Generated filename := file.GeneratedFilenamePrefix + "_http.pb.go" g := gen.NewGeneratedFile(filename, file.GoImportPath) g.P("// Code generated by protoc-gen-go-http. DO NOT EDIT.") + g.P("// versions:") + g.P(fmt.Sprintf("// protoc-gen-go-http %s", Version)) g.P() g.P("package ", file.GoPackageName) g.P() @@ -43,12 +44,10 @@ func generateFileContent(gen *protogen.Plugin, file *protogen.File, g *protogen. } g.P("// This is a compile-time assertion to ensure that this generated file") g.P("// is compatible with the kratos package it is being compiled against.") - g.P("var _ = new(", httpPackage.Ident("Request"), ")") g.P("var _ = new(", contextPackage.Ident("Context"), ")") g.P("var _ = new(", middlewarePackage.Ident("Middleware"), ")") g.P("var _ = new(", transportPackage.Ident("Transporter"), ")") g.P("var _ = ", bindingPackage.Ident("BindVars")) - g.P("var _ = ", muxPackage.Ident("NewRouter")) g.P("const _ = ", transportHTTPPackage.Ident("SupportPackageIsVersion1")) g.P() @@ -104,11 +103,13 @@ func buildHTTPRule(g *protogen.GeneratedFile, m *protogen.Method, rule *annotati method string body string responseBody string + isQuery bool ) switch pattern := rule.Pattern.(type) { case *annotations.HttpRule_Get: path = pattern.Get method = "GET" + isQuery = true case *annotations.HttpRule_Put: path = pattern.Put method = "PUT" @@ -142,6 +143,7 @@ func buildHTTPRule(g *protogen.GeneratedFile, m *protogen.Method, rule *annotati } else if responseBody != "" { md.ResponseBody = "." + camelCaseVars(responseBody) } + md.IsQuery = isQuery return md } diff --git a/cmd/protoc-gen-go-http/template.go b/cmd/protoc-gen-go-http/template.go index 372453639..6b781d15f 100644 --- a/cmd/protoc-gen-go-http/template.go +++ b/cmd/protoc-gen-go-http/template.go @@ -9,77 +9,72 @@ import ( var httpTemplate = ` {{$svrType := .ServiceType}} {{$svrName := .ServiceName}} -type {{.ServiceType}}Handler interface { -{{range .MethodSets}} +type {{.ServiceType}}HTTPServer interface { +{{- range .MethodSets}} {{.Name}}(context.Context, *{{.Request}}) (*{{.Reply}}, error) -{{end}} +{{- end}} } -func New{{.ServiceType}}Handler(srv {{.ServiceType}}Handler, opts ...http1.HandleOption) http.Handler { - h := http1.DefaultHandleOptions() - for _, o := range opts { - o(&h) - } - r := mux.NewRouter() - {{range .Methods}} - r.HandleFunc("{{.Path}}", func(w http.ResponseWriter, r *http.Request) { +func Register{{.ServiceType}}HTTPServer(s *http.Server, srv {{.ServiceType}}HTTPServer) { + r := s.Route("/") + {{- range .Methods}} + r.{{.Method}}("{{.Path}}", _{{$svrType}}_{{.Name}}{{.Num}}_HTTP_Handler(srv)) + {{- end}} +} + +{{range .Methods}} +func _{{$svrType}}_{{.Name}}{{.Num}}_HTTP_Handler(srv {{$svrType}}HTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { var in {{.Request}} - if err := h.Decode(r, &in{{.Body}}); err != nil { - h.Error(w, r, err) - return + if err := ctx.Bind(&in{{.Body}}); err != nil { + return err } - {{if ne (len .Vars) 0}} - if err := binding.BindVars(mux.Vars(r), &in); err != nil { - h.Error(w, r, err) - return + {{- if ne (len .Vars) 0}} + if err := binding.BindVars(ctx.Vars(), &in); err != nil { + return err } - {{end}} - next := func(ctx context.Context, req interface{}) (interface{}, error) { + {{- end}} + transport.SetOperation(ctx,"/{{$svrName}}/{{.Name}}") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { return srv.{{.Name}}(ctx, req.(*{{.Request}})) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx,"/{{$svrName}}/{{.Name}}") - out, err := next(ctx, &in) + }) + out, err := h(ctx, &in) if err != nil { - h.Error(w, r, err) - return + return err } reply := out.(*{{.Reply}}) - if err := h.Encode(w, r, reply{{.ResponseBody}}); err != nil { - h.Error(w, r, err) - } - }).Methods("{{.Method}}") - {{end}} - return r + return ctx.Result(200, reply{{.ResponseBody}}) + } } +{{end}} type {{.ServiceType}}HTTPClient interface { -{{range .MethodSets}} - {{.Name}}(ctx context.Context, req *{{.Request}}, opts ...http1.CallOption) (rsp *{{.Reply}}, err error) -{{end}} +{{- range .MethodSets}} + {{.Name}}(ctx context.Context, req *{{.Request}}, opts ...http.CallOption) (rsp *{{.Reply}}, err error) +{{- end}} } type {{.ServiceType}}HTTPClientImpl struct{ - cc *http1.Client + cc *http.Client } -func New{{.ServiceType}}HTTPClient (client *http1.Client) {{.ServiceType}}HTTPClient { +func New{{.ServiceType}}HTTPClient (client *http.Client) {{.ServiceType}}HTTPClient { return &{{.ServiceType}}HTTPClientImpl{client} } {{range .MethodSets}} -func (c *{{$svrType}}HTTPClientImpl) {{.Name}}(ctx context.Context, in *{{.Request}}, opts ...http1.CallOption) (*{{.Reply}}, error) { +func (c *{{$svrType}}HTTPClientImpl) {{.Name}}(ctx context.Context, in *{{.Request}}, opts ...http.CallOption) (*{{.Reply}}, error) { var out {{.Reply}} - path := binding.EncodePath("{{.Method}}", "{{.Path}}", in) - opts = append(opts, http1.Method("/{{$svrName}}/{{.Name}}")) - {{if .HasBody }} + path := binding.EncodeVars("{{.Path}}", in, {{.IsQuery}}) + opts = append(opts, http.Operation("/{{$svrName}}/{{.Name}}")) + {{if .HasBody -}} err := c.cc.Invoke(ctx, "{{.Method}}", path, in{{.Body}}, &out{{.ResponseBody}}, opts...) - {{else}} + {{else -}} err := c.cc.Invoke(ctx, "{{.Method}}", path, nil, &out{{.ResponseBody}}, opts...) - {{end}} + {{end -}} + if err != nil { + return nil, err + } return &out, err } {{end}} @@ -106,6 +101,7 @@ type methodDesc struct { HasBody bool Body string ResponseBody string + IsQuery bool } func (s *serviceDesc) execute() string { @@ -121,5 +117,5 @@ func (s *serviceDesc) execute() string { if err := tmpl.Execute(buf, s); err != nil { panic(err) } - return string(buf.Bytes()) + return strings.Trim(string(buf.Bytes()), "\r\n") } diff --git a/cmd/protoc-gen-go-http/version.go b/cmd/protoc-gen-go-http/version.go new file mode 100644 index 000000000..71321b5e0 --- /dev/null +++ b/cmd/protoc-gen-go-http/version.go @@ -0,0 +1,6 @@ +package main + +const ( + // Version is protoc-gen-go-http version + Version = "v2.0.0-rc3" +) diff --git a/encoding/json/json_test.go b/encoding/json/json_test.go new file mode 100644 index 000000000..06d80ee2f --- /dev/null +++ b/encoding/json/json_test.go @@ -0,0 +1,80 @@ +package json + +import ( + "bytes" + "strings" + "testing" +) + +type testEmbed struct { + Level1a int `json:"a"` + Level1b int `json:"b"` + Level1c int `json:"c"` +} + +type testMessage struct { + Field1 string `json:"a"` + Field2 string `json:"b"` + Field3 string `json:"c"` + Embed *testEmbed `json:"embed,omitempty"` +} + +func TestJSON_Marshal(t *testing.T) { + tests := []struct { + input interface{} + expect string + }{ + { + input: &testMessage{}, + expect: `{"a":"","b":"","c":""}`, + }, + { + input: &testMessage{Field1: "a", Field2: "b", Field3: "c"}, + expect: `{"a":"a","b":"b","c":"c"}`, + }, + } + for _, v := range tests { + data, err := (codec{}).Marshal(v.input) + if err != nil { + t.Errorf("marshal(%#v): %s", v.input, err) + } + if got, want := string(data), v.expect; got != want { + if strings.Contains(want, "\n") { + t.Errorf("marshal(%#v):\nHAVE:\n%s\nWANT:\n%s", v.input, got, want) + } else { + t.Errorf("marshal(%#v):\nhave %#q\nwant %#q", v.input, got, want) + } + } + } +} + +func TestJSON_Unmarshal(t *testing.T) { + p := &testMessage{} + tests := []struct { + input string + expect interface{} + }{ + { + input: `{"a":"","b":"","c":""}`, + expect: &testMessage{}, + }, + { + input: `{"a":"a","b":"b","c":"c"}`, + expect: &p, + }, + } + for _, v := range tests { + want := []byte(v.input) + err := (codec{}).Unmarshal(want, &v.expect) + if err != nil { + t.Errorf("marshal(%#v): %s", v.input, err) + } + got, err := codec{}.Marshal(v.expect) + if err != nil { + t.Errorf("marshal(%#v): %s", v.input, err) + } + if !bytes.Equal(got, want) { + t.Errorf("marshal(%#v):\nhave %#q\nwant %#q", v.input, got, want) + } + } +} diff --git a/examples/blog/api/blog/v1/blog_http.pb.go b/examples/blog/api/blog/v1/blog_http.pb.go index 4a0ceff26..93e2c7718 100644 --- a/examples/blog/api/blog/v1/blog_http.pb.go +++ b/examples/blog/api/blog/v1/blog_http.pb.go @@ -1,4 +1,6 @@ // Code generated by protoc-gen-go-http. DO NOT EDIT. +// versions: +// protoc-gen-go-http v2.0.0-rc3 package v1 @@ -6,256 +8,207 @@ import ( context "context" middleware "github.com/go-kratos/kratos/v2/middleware" transport "github.com/go-kratos/kratos/v2/transport" - http1 "github.com/go-kratos/kratos/v2/transport/http" + http "github.com/go-kratos/kratos/v2/transport/http" binding "github.com/go-kratos/kratos/v2/transport/http/binding" - mux "github.com/gorilla/mux" - http "net/http" ) // This is a compile-time assertion to ensure that this generated file // is compatible with the kratos package it is being compiled against. -var _ = new(http.Request) var _ = new(context.Context) var _ = new(middleware.Middleware) var _ = new(transport.Transporter) var _ = binding.BindVars -var _ = mux.NewRouter -const _ = http1.SupportPackageIsVersion1 +const _ = http.SupportPackageIsVersion1 -type BlogServiceHandler interface { +type BlogServiceHTTPServer interface { CreateArticle(context.Context, *CreateArticleRequest) (*CreateArticleReply, error) - DeleteArticle(context.Context, *DeleteArticleRequest) (*DeleteArticleReply, error) - GetArticle(context.Context, *GetArticleRequest) (*GetArticleReply, error) - ListArticle(context.Context, *ListArticleRequest) (*ListArticleReply, error) - UpdateArticle(context.Context, *UpdateArticleRequest) (*UpdateArticleReply, error) } -func NewBlogServiceHandler(srv BlogServiceHandler, opts ...http1.HandleOption) http.Handler { - h := http1.DefaultHandleOptions() - for _, o := range opts { - o(&h) - } - r := mux.NewRouter() +func RegisterBlogServiceHTTPServer(s *http.Server, srv BlogServiceHTTPServer) { + r := s.Route("/") + r.POST("/v1/article/", _BlogService_CreateArticle0_HTTP_Handler(srv)) + r.PUT("/v1/article/{id}", _BlogService_UpdateArticle0_HTTP_Handler(srv)) + r.DELETE("/v1/article/{id}", _BlogService_DeleteArticle0_HTTP_Handler(srv)) + r.GET("/v1/article/{id}", _BlogService_GetArticle0_HTTP_Handler(srv)) + r.GET("/v1/article/", _BlogService_ListArticle0_HTTP_Handler(srv)) +} - r.HandleFunc("/v1/article/", func(w http.ResponseWriter, r *http.Request) { +func _BlogService_CreateArticle0_HTTP_Handler(srv BlogServiceHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { var in CreateArticleRequest - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return + if err := ctx.Bind(&in); err != nil { + return err } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { + transport.SetOperation(ctx, "/blog.api.v1.BlogService/CreateArticle") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { return srv.CreateArticle(ctx, req.(*CreateArticleRequest)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/blog.api.v1.BlogService/CreateArticle") - out, err := next(ctx, &in) + }) + out, err := h(ctx, &in) if err != nil { - h.Error(w, r, err) - return + return err } reply := out.(*CreateArticleReply) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("POST") + return ctx.Result(200, reply) + } +} - r.HandleFunc("/v1/article/{id}", func(w http.ResponseWriter, r *http.Request) { +func _BlogService_UpdateArticle0_HTTP_Handler(srv BlogServiceHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { var in UpdateArticleRequest - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return + if err := ctx.Bind(&in); err != nil { + return err } - - if err := binding.BindVars(mux.Vars(r), &in); err != nil { - h.Error(w, r, err) - return + if err := binding.BindVars(ctx.Vars(), &in); err != nil { + return err } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { + transport.SetOperation(ctx, "/blog.api.v1.BlogService/UpdateArticle") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { return srv.UpdateArticle(ctx, req.(*UpdateArticleRequest)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/blog.api.v1.BlogService/UpdateArticle") - out, err := next(ctx, &in) + }) + out, err := h(ctx, &in) if err != nil { - h.Error(w, r, err) - return + return err } reply := out.(*UpdateArticleReply) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("PUT") + return ctx.Result(200, reply) + } +} - r.HandleFunc("/v1/article/{id}", func(w http.ResponseWriter, r *http.Request) { +func _BlogService_DeleteArticle0_HTTP_Handler(srv BlogServiceHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { var in DeleteArticleRequest - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return + if err := ctx.Bind(&in); err != nil { + return err } - - if err := binding.BindVars(mux.Vars(r), &in); err != nil { - h.Error(w, r, err) - return + if err := binding.BindVars(ctx.Vars(), &in); err != nil { + return err } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { + transport.SetOperation(ctx, "/blog.api.v1.BlogService/DeleteArticle") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { return srv.DeleteArticle(ctx, req.(*DeleteArticleRequest)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/blog.api.v1.BlogService/DeleteArticle") - out, err := next(ctx, &in) + }) + out, err := h(ctx, &in) if err != nil { - h.Error(w, r, err) - return + return err } reply := out.(*DeleteArticleReply) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("DELETE") + return ctx.Result(200, reply) + } +} - r.HandleFunc("/v1/article/{id}", func(w http.ResponseWriter, r *http.Request) { +func _BlogService_GetArticle0_HTTP_Handler(srv BlogServiceHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { var in GetArticleRequest - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return + if err := ctx.Bind(&in); err != nil { + return err } - - if err := binding.BindVars(mux.Vars(r), &in); err != nil { - h.Error(w, r, err) - return + if err := binding.BindVars(ctx.Vars(), &in); err != nil { + return err } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { + transport.SetOperation(ctx, "/blog.api.v1.BlogService/GetArticle") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { return srv.GetArticle(ctx, req.(*GetArticleRequest)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/blog.api.v1.BlogService/GetArticle") - out, err := next(ctx, &in) + }) + out, err := h(ctx, &in) if err != nil { - h.Error(w, r, err) - return + return err } reply := out.(*GetArticleReply) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("GET") + return ctx.Result(200, reply) + } +} - r.HandleFunc("/v1/article/", func(w http.ResponseWriter, r *http.Request) { +func _BlogService_ListArticle0_HTTP_Handler(srv BlogServiceHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { var in ListArticleRequest - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return + if err := ctx.Bind(&in); err != nil { + return err } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { + transport.SetOperation(ctx, "/blog.api.v1.BlogService/ListArticle") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { return srv.ListArticle(ctx, req.(*ListArticleRequest)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/blog.api.v1.BlogService/ListArticle") - out, err := next(ctx, &in) + }) + out, err := h(ctx, &in) if err != nil { - h.Error(w, r, err) - return + return err } reply := out.(*ListArticleReply) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("GET") - - return r + return ctx.Result(200, reply) + } } type BlogServiceHTTPClient interface { - CreateArticle(ctx context.Context, req *CreateArticleRequest, opts ...http1.CallOption) (rsp *CreateArticleReply, err error) - - DeleteArticle(ctx context.Context, req *DeleteArticleRequest, opts ...http1.CallOption) (rsp *DeleteArticleReply, err error) - - GetArticle(ctx context.Context, req *GetArticleRequest, opts ...http1.CallOption) (rsp *GetArticleReply, err error) - - ListArticle(ctx context.Context, req *ListArticleRequest, opts ...http1.CallOption) (rsp *ListArticleReply, err error) - - UpdateArticle(ctx context.Context, req *UpdateArticleRequest, opts ...http1.CallOption) (rsp *UpdateArticleReply, err error) + CreateArticle(ctx context.Context, req *CreateArticleRequest, opts ...http.CallOption) (rsp *CreateArticleReply, err error) + DeleteArticle(ctx context.Context, req *DeleteArticleRequest, opts ...http.CallOption) (rsp *DeleteArticleReply, err error) + GetArticle(ctx context.Context, req *GetArticleRequest, opts ...http.CallOption) (rsp *GetArticleReply, err error) + ListArticle(ctx context.Context, req *ListArticleRequest, opts ...http.CallOption) (rsp *ListArticleReply, err error) + UpdateArticle(ctx context.Context, req *UpdateArticleRequest, opts ...http.CallOption) (rsp *UpdateArticleReply, err error) } type BlogServiceHTTPClientImpl struct { - cc *http1.Client + cc *http.Client } -func NewBlogServiceHTTPClient(client *http1.Client) BlogServiceHTTPClient { +func NewBlogServiceHTTPClient(client *http.Client) BlogServiceHTTPClient { return &BlogServiceHTTPClientImpl{client} } -func (c *BlogServiceHTTPClientImpl) CreateArticle(ctx context.Context, in *CreateArticleRequest, opts ...http1.CallOption) (*CreateArticleReply, error) { +func (c *BlogServiceHTTPClientImpl) CreateArticle(ctx context.Context, in *CreateArticleRequest, opts ...http.CallOption) (*CreateArticleReply, error) { var out CreateArticleReply - path := binding.EncodePath("POST", "/v1/article/", in) - opts = append(opts, http1.Method("/blog.api.v1.BlogService/CreateArticle")) - + path := binding.EncodeVars("/v1/article/", in, false) + opts = append(opts, http.Operation("/blog.api.v1.BlogService/CreateArticle")) err := c.cc.Invoke(ctx, "POST", path, in, &out, opts...) - + if err != nil { + return nil, err + } return &out, err } -func (c *BlogServiceHTTPClientImpl) DeleteArticle(ctx context.Context, in *DeleteArticleRequest, opts ...http1.CallOption) (*DeleteArticleReply, error) { +func (c *BlogServiceHTTPClientImpl) DeleteArticle(ctx context.Context, in *DeleteArticleRequest, opts ...http.CallOption) (*DeleteArticleReply, error) { var out DeleteArticleReply - path := binding.EncodePath("DELETE", "/v1/article/{id}", in) - opts = append(opts, http1.Method("/blog.api.v1.BlogService/DeleteArticle")) - + path := binding.EncodeVars("/v1/article/{id}", in, false) + opts = append(opts, http.Operation("/blog.api.v1.BlogService/DeleteArticle")) err := c.cc.Invoke(ctx, "DELETE", path, nil, &out, opts...) - + if err != nil { + return nil, err + } return &out, err } -func (c *BlogServiceHTTPClientImpl) GetArticle(ctx context.Context, in *GetArticleRequest, opts ...http1.CallOption) (*GetArticleReply, error) { +func (c *BlogServiceHTTPClientImpl) GetArticle(ctx context.Context, in *GetArticleRequest, opts ...http.CallOption) (*GetArticleReply, error) { var out GetArticleReply - path := binding.EncodePath("GET", "/v1/article/{id}", in) - opts = append(opts, http1.Method("/blog.api.v1.BlogService/GetArticle")) - + path := binding.EncodeVars("/v1/article/{id}", in, true) + opts = append(opts, http.Operation("/blog.api.v1.BlogService/GetArticle")) err := c.cc.Invoke(ctx, "GET", path, nil, &out, opts...) - + if err != nil { + return nil, err + } return &out, err } -func (c *BlogServiceHTTPClientImpl) ListArticle(ctx context.Context, in *ListArticleRequest, opts ...http1.CallOption) (*ListArticleReply, error) { +func (c *BlogServiceHTTPClientImpl) ListArticle(ctx context.Context, in *ListArticleRequest, opts ...http.CallOption) (*ListArticleReply, error) { var out ListArticleReply - path := binding.EncodePath("GET", "/v1/article/", in) - opts = append(opts, http1.Method("/blog.api.v1.BlogService/ListArticle")) - + path := binding.EncodeVars("/v1/article/", in, true) + opts = append(opts, http.Operation("/blog.api.v1.BlogService/ListArticle")) err := c.cc.Invoke(ctx, "GET", path, nil, &out, opts...) - + if err != nil { + return nil, err + } return &out, err } -func (c *BlogServiceHTTPClientImpl) UpdateArticle(ctx context.Context, in *UpdateArticleRequest, opts ...http1.CallOption) (*UpdateArticleReply, error) { +func (c *BlogServiceHTTPClientImpl) UpdateArticle(ctx context.Context, in *UpdateArticleRequest, opts ...http.CallOption) (*UpdateArticleReply, error) { var out UpdateArticleReply - path := binding.EncodePath("PUT", "/v1/article/{id}", in) - opts = append(opts, http1.Method("/blog.api.v1.BlogService/UpdateArticle")) - + path := binding.EncodeVars("/v1/article/{id}", in, false) + opts = append(opts, http.Operation("/blog.api.v1.BlogService/UpdateArticle")) err := c.cc.Invoke(ctx, "PUT", path, in, &out, opts...) - + if err != nil { + return nil, err + } return &out, err } diff --git a/examples/blog/api/blog/v1/error_reason.pb.go b/examples/blog/api/blog/v1/error_reason.pb.go deleted file mode 100644 index 708113e74..000000000 --- a/examples/blog/api/blog/v1/error_reason.pb.go +++ /dev/null @@ -1,134 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.26.0 -// protoc v3.15.7 -// source: blog/api/blog/v1/error_reason.proto - -package v1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ErrorReason int32 - -const ( - ErrorReason_TITLE_MISSING ErrorReason = 0 - ErrorReason_CONTENTMISSING ErrorReason = 1 -) - -// Enum value maps for ErrorReason. -var ( - ErrorReason_name = map[int32]string{ - 0: "TITLE_MISSING", - 1: "CONTENTMISSING", - } - ErrorReason_value = map[string]int32{ - "TITLE_MISSING": 0, - "CONTENTMISSING": 1, - } -) - -func (x ErrorReason) Enum() *ErrorReason { - p := new(ErrorReason) - *p = x - return p -} - -func (x ErrorReason) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ErrorReason) Descriptor() protoreflect.EnumDescriptor { - return file_blog_api_blog_v1_error_reason_proto_enumTypes[0].Descriptor() -} - -func (ErrorReason) Type() protoreflect.EnumType { - return &file_blog_api_blog_v1_error_reason_proto_enumTypes[0] -} - -func (x ErrorReason) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ErrorReason.Descriptor instead. -func (ErrorReason) EnumDescriptor() ([]byte, []int) { - return file_blog_api_blog_v1_error_reason_proto_rawDescGZIP(), []int{0} -} - -var File_blog_api_blog_v1_error_reason_proto protoreflect.FileDescriptor - -var file_blog_api_blog_v1_error_reason_proto_rawDesc = []byte{ - 0x0a, 0x23, 0x62, 0x6c, 0x6f, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x62, 0x6c, 0x6f, 0x67, 0x2f, - 0x76, 0x31, 0x2f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x61, 0x70, 0x69, 0x2e, 0x62, 0x6c, 0x6f, 0x67, 0x2e, - 0x76, 0x31, 0x2a, 0x34, 0x0a, 0x0b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x49, 0x54, 0x4c, 0x45, 0x5f, 0x4d, 0x49, 0x53, 0x53, 0x49, - 0x4e, 0x47, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x4f, 0x4e, 0x54, 0x45, 0x4e, 0x54, 0x4d, - 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x42, 0x57, 0x0a, 0x0e, 0x62, 0x6c, 0x6f, 0x67, - 0x2e, 0x76, 0x31, 0x2e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x2d, 0x6b, 0x72, 0x61, 0x74, - 0x6f, 0x73, 0x2f, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x73, 0x2f, 0x62, 0x6c, 0x6f, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x76, - 0x31, 0xa2, 0x02, 0x0d, 0x41, 0x50, 0x49, 0x42, 0x6c, 0x6f, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_blog_api_blog_v1_error_reason_proto_rawDescOnce sync.Once - file_blog_api_blog_v1_error_reason_proto_rawDescData = file_blog_api_blog_v1_error_reason_proto_rawDesc -) - -func file_blog_api_blog_v1_error_reason_proto_rawDescGZIP() []byte { - file_blog_api_blog_v1_error_reason_proto_rawDescOnce.Do(func() { - file_blog_api_blog_v1_error_reason_proto_rawDescData = protoimpl.X.CompressGZIP(file_blog_api_blog_v1_error_reason_proto_rawDescData) - }) - return file_blog_api_blog_v1_error_reason_proto_rawDescData -} - -var file_blog_api_blog_v1_error_reason_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_blog_api_blog_v1_error_reason_proto_goTypes = []interface{}{ - (ErrorReason)(0), // 0: api.blog.v1.ErrorReason -} -var file_blog_api_blog_v1_error_reason_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_blog_api_blog_v1_error_reason_proto_init() } -func file_blog_api_blog_v1_error_reason_proto_init() { - if File_blog_api_blog_v1_error_reason_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_blog_api_blog_v1_error_reason_proto_rawDesc, - NumEnums: 1, - NumMessages: 0, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_blog_api_blog_v1_error_reason_proto_goTypes, - DependencyIndexes: file_blog_api_blog_v1_error_reason_proto_depIdxs, - EnumInfos: file_blog_api_blog_v1_error_reason_proto_enumTypes, - }.Build() - File_blog_api_blog_v1_error_reason_proto = out.File - file_blog_api_blog_v1_error_reason_proto_rawDesc = nil - file_blog_api_blog_v1_error_reason_proto_goTypes = nil - file_blog_api_blog_v1_error_reason_proto_depIdxs = nil -} diff --git a/examples/blog/api/blog/v1/error_reason.proto b/examples/blog/api/blog/v1/error_reason.proto deleted file mode 100644 index 0ce01b003..000000000 --- a/examples/blog/api/blog/v1/error_reason.proto +++ /dev/null @@ -1,14 +0,0 @@ -syntax = "proto3"; - -package api.blog.v1; - -// 多语言特定包名,用于源代码引用 -option go_package = "github.com/go-kratos/kratos/examples/blog/api/v1;v1"; -option java_multiple_files = true; -option java_package = "blog.v1.errors"; -option objc_class_prefix = "APIBlogErrors"; - -enum ErrorReason { - TITLE_MISSING = 0; - CONTENTMISSING = 1; -} diff --git a/examples/blog/cmd/blog/main.go b/examples/blog/cmd/blog/main.go index 7a383835c..51e352ad6 100644 --- a/examples/blog/cmd/blog/main.go +++ b/examples/blog/cmd/blog/main.go @@ -6,7 +6,7 @@ import ( "os" "time" - "github.com/go-kratos/kratos/examples/blog/api/blog/v1" + v1 "github.com/go-kratos/kratos/examples/blog/api/blog/v1" "github.com/go-kratos/kratos/examples/blog/internal/conf" "github.com/go-kratos/kratos/v2" "github.com/go-kratos/kratos/v2/config" @@ -19,7 +19,6 @@ import ( "go.opentelemetry.io/otel/sdk/resource" tracesdk "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/semconv" - "gopkg.in/yaml.v2" ) // go build -ldflags "-X main.Version=x.y.z" @@ -76,9 +75,6 @@ func main() { config.WithSource( file.NewSource(flagconf), ), - config.WithDecoder(func(kv *config.KeyValue, v map[string]interface{}) error { - return yaml.Unmarshal(kv.Value, v) - }), ) if err := config.Load(); err != nil { panic(err) diff --git a/examples/blog/cmd/blog/wire_gen.go b/examples/blog/cmd/blog/wire_gen.go index a5a1bb8e9..c5b8eada4 100644 --- a/examples/blog/cmd/blog/wire_gen.go +++ b/examples/blog/cmd/blog/wire_gen.go @@ -27,8 +27,8 @@ func initApp(confServer *conf.Server, confData *conf.Data, traceTracerProvider t articleRepo := data.NewArticleRepo(dataData, logger) articleUsecase := biz.NewArticleUsecase(articleRepo, logger) blogService := service.NewBlogService(articleUsecase, logger) - httpServer := server.NewHTTPServer(confServer, traceTracerProvider, blogService) - grpcServer := server.NewGRPCServer(confServer, traceTracerProvider, blogService) + httpServer := server.NewHTTPServer(confServer, logger, traceTracerProvider, blogService) + grpcServer := server.NewGRPCServer(confServer, logger, traceTracerProvider, blogService) app := newApp(logger, httpServer, grpcServer) return app, func() { cleanup() diff --git a/examples/blog/internal/server/grpc.go b/examples/blog/internal/server/grpc.go index fbee36592..d8f8d73ae 100644 --- a/examples/blog/internal/server/grpc.go +++ b/examples/blog/internal/server/grpc.go @@ -14,12 +14,12 @@ import ( ) // NewGRPCServer new a gRPC server. -func NewGRPCServer(c *conf.Server, tracer trace.TracerProvider, blog *service.BlogService) *grpc.Server { +func NewGRPCServer(c *conf.Server, logger log.Logger, tracer trace.TracerProvider, blog *service.BlogService) *grpc.Server { var opts = []grpc.ServerOption{ grpc.Middleware( recovery.Recovery(), tracing.Server(tracing.WithTracerProvider(tracer)), - logging.Server(log.DefaultLogger), + logging.Server(logger), validate.Validator(), ), } diff --git a/examples/blog/internal/server/http.go b/examples/blog/internal/server/http.go index 59cb4a6d5..a394fc1ec 100644 --- a/examples/blog/internal/server/http.go +++ b/examples/blog/internal/server/http.go @@ -14,8 +14,15 @@ import ( ) // NewHTTPServer new a HTTP server. -func NewHTTPServer(c *conf.Server, tracer trace.TracerProvider, blog *service.BlogService) *http.Server { - var opts []http.ServerOption +func NewHTTPServer(c *conf.Server, logger log.Logger, tracer trace.TracerProvider, blog *service.BlogService) *http.Server { + var opts = []http.ServerOption{ + http.Middleware( + recovery.Recovery(), + tracing.Server(tracing.WithTracerProvider(tracer)), + logging.Server(logger), + validate.Validator(), + ), + } if c.Http.Network != "" { opts = append(opts, http.Network(c.Http.Network)) } @@ -25,13 +32,7 @@ func NewHTTPServer(c *conf.Server, tracer trace.TracerProvider, blog *service.Bl if c.Http.Timeout != nil { opts = append(opts, http.Timeout(c.Http.Timeout.AsDuration())) } - m := http.Middleware( - recovery.Recovery(), - tracing.Server(tracing.WithTracerProvider(tracer)), - logging.Server(log.DefaultLogger), - validate.Validator(), - ) srv := http.NewServer(opts...) - srv.HandlePrefix("/", v1.NewBlogServiceHandler(blog, m)) + v1.RegisterBlogServiceHTTPServer(srv, blog) return srv } diff --git a/examples/helloworld/helloworld/helloworld_http.pb.go b/examples/helloworld/helloworld/helloworld_http.pb.go index f358a62ad..bd368ad60 100644 --- a/examples/helloworld/helloworld/helloworld_http.pb.go +++ b/examples/helloworld/helloworld/helloworld_http.pb.go @@ -1,4 +1,6 @@ // Code generated by protoc-gen-go-http. DO NOT EDIT. +// versions: +// protoc-gen-go-http v2.0.0-rc3 package helloworld @@ -6,86 +8,69 @@ import ( context "context" middleware "github.com/go-kratos/kratos/v2/middleware" transport "github.com/go-kratos/kratos/v2/transport" - http1 "github.com/go-kratos/kratos/v2/transport/http" + http "github.com/go-kratos/kratos/v2/transport/http" binding "github.com/go-kratos/kratos/v2/transport/http/binding" - mux "github.com/gorilla/mux" - http "net/http" ) // This is a compile-time assertion to ensure that this generated file // is compatible with the kratos package it is being compiled against. -var _ = new(http.Request) var _ = new(context.Context) var _ = new(middleware.Middleware) var _ = new(transport.Transporter) var _ = binding.BindVars -var _ = mux.NewRouter -const _ = http1.SupportPackageIsVersion1 +const _ = http.SupportPackageIsVersion1 -type GreeterHandler interface { +type GreeterHTTPServer interface { SayHello(context.Context, *HelloRequest) (*HelloReply, error) } -func NewGreeterHandler(srv GreeterHandler, opts ...http1.HandleOption) http.Handler { - h := http1.DefaultHandleOptions() - for _, o := range opts { - o(&h) - } - r := mux.NewRouter() +func RegisterGreeterHTTPServer(s *http.Server, srv GreeterHTTPServer) { + r := s.Route("/") + r.GET("/helloworld/{name}", _Greeter_SayHello0_HTTP_Handler(srv)) +} - r.HandleFunc("/helloworld/{name}", func(w http.ResponseWriter, r *http.Request) { +func _Greeter_SayHello0_HTTP_Handler(srv GreeterHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { var in HelloRequest - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return + if err := ctx.Bind(&in); err != nil { + return err } - - if err := binding.BindVars(mux.Vars(r), &in); err != nil { - h.Error(w, r, err) - return + if err := binding.BindVars(ctx.Vars(), &in); err != nil { + return err } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { + transport.SetOperation(ctx, "/helloworld.Greeter/SayHello") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { return srv.SayHello(ctx, req.(*HelloRequest)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/helloworld.Greeter/SayHello") - out, err := next(ctx, &in) + }) + out, err := h(ctx, &in) if err != nil { - h.Error(w, r, err) - return + return err } reply := out.(*HelloReply) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("GET") - - return r + return ctx.Result(200, reply) + } } type GreeterHTTPClient interface { - SayHello(ctx context.Context, req *HelloRequest, opts ...http1.CallOption) (rsp *HelloReply, err error) + SayHello(ctx context.Context, req *HelloRequest, opts ...http.CallOption) (rsp *HelloReply, err error) } type GreeterHTTPClientImpl struct { - cc *http1.Client + cc *http.Client } -func NewGreeterHTTPClient(client *http1.Client) GreeterHTTPClient { +func NewGreeterHTTPClient(client *http.Client) GreeterHTTPClient { return &GreeterHTTPClientImpl{client} } -func (c *GreeterHTTPClientImpl) SayHello(ctx context.Context, in *HelloRequest, opts ...http1.CallOption) (*HelloReply, error) { +func (c *GreeterHTTPClientImpl) SayHello(ctx context.Context, in *HelloRequest, opts ...http.CallOption) (*HelloReply, error) { var out HelloReply - path := binding.EncodePath("GET", "/helloworld/{name}", in) - opts = append(opts, http1.Method("/helloworld.Greeter/SayHello")) - + path := binding.EncodeVars("/helloworld/{name}", in, true) + opts = append(opts, http.Operation("/helloworld.Greeter/SayHello")) err := c.cc.Invoke(ctx, "GET", path, nil, &out, opts...) - + if err != nil { + return nil, err + } return &out, err } diff --git a/examples/helloworld/server/main.go b/examples/helloworld/server/main.go index a196553d1..fb51effae 100644 --- a/examples/helloworld/server/main.go +++ b/examples/helloworld/server/main.go @@ -42,25 +42,23 @@ func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloRe func main() { logger := log.NewStdLogger(os.Stdout) - log := log.NewHelper(logger) - + s := &server{} grpcSrv := grpc.NewServer( grpc.Address(":9000"), grpc.Middleware( recovery.Recovery(), logging.Server(logger), - )) - - s := &server{} - pb.RegisterGreeterServer(grpcSrv, s) - - httpSrv := http.NewServer(http.Address(":8000")) - httpSrv.HandlePrefix("/", pb.NewGreeterHandler(s, + ), + ) + httpSrv := http.NewServer( + http.Address(":8000"), http.Middleware( recovery.Recovery(), logging.Server(logger), - )), + ), ) + pb.RegisterGreeterServer(grpcSrv, s) + pb.RegisterGreeterHTTPServer(httpSrv, s) app := kratos.New( kratos.Name(Name), @@ -71,6 +69,6 @@ func main() { ) if err := app.Run(); err != nil { - log.Error(err) + panic(err) } } diff --git a/examples/http/handler/main.go b/examples/http/handler/main.go deleted file mode 100644 index 53913bec0..000000000 --- a/examples/http/handler/main.go +++ /dev/null @@ -1,52 +0,0 @@ -package main - -import ( - "context" - "log" - - "github.com/go-kratos/kratos/v2" - "github.com/go-kratos/kratos/v2/transport/http" - "github.com/gorilla/mux" -) - -// User is a user model. -type User struct { - ID string `json:"id"` - Name string `json:"name"` -} - -// UserService is a user service. -type UserService struct{ users map[string]*User } - -// Get get a user from memory. -func (u *UserService) Get(ctx context.Context, user *User) (*User, error) { - return u.users[user.ID], nil -} - -// Add add a user to memory. -func (u *UserService) Add(ctx context.Context, user *User) (*User, error) { - u.users[user.ID] = user - return user, nil -} - -func main() { - us := &UserService{ - users: make(map[string]*User), - } - router := mux.NewRouter() - router.Handle("/users/add", http.NewHandler(us.Add)).Methods("POST") - router.Handle("/users/detail", http.NewHandler(us.Get)).Methods("GET") - - httpSrv := http.NewServer(http.Address(":8000")) - httpSrv.HandlePrefix("/", router) - - app := kratos.New( - kratos.Name("handler"), - kratos.Server( - httpSrv, - ), - ) - if err := app.Run(); err != nil { - log.Println(err) - } -} diff --git a/examples/http/middlewares/handlers.go b/examples/http/middlewares/handlers.go new file mode 100644 index 000000000..0575be1c0 --- /dev/null +++ b/examples/http/middlewares/handlers.go @@ -0,0 +1,28 @@ +package main + +import ( + "context" + + "github.com/go-kratos/kratos/examples/helloworld/helloworld" + "github.com/go-kratos/kratos/v2/transport" + "github.com/go-kratos/kratos/v2/transport/http" + "github.com/go-kratos/kratos/v2/transport/http/binding" +) + +func sayHelloHandler(ctx http.Context) error { + var in helloworld.HelloRequest + if err := ctx.Bind(&in); err != nil { + return err + } + + // binding /hello/{name} to in.Name + if err := binding.BindVars(ctx.Vars(), &in); err != nil { + return err + } + + transport.SetOperation(ctx, "/helloworld.Greeter/SayHello") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { + return &helloworld.HelloReply{Message: "test:" + req.(*helloworld.HelloRequest).Name}, nil + }) + return ctx.Returns(h(ctx, &in)) +} diff --git a/examples/http/middlewares/main.go b/examples/http/middlewares/main.go new file mode 100644 index 000000000..4f2418adb --- /dev/null +++ b/examples/http/middlewares/main.go @@ -0,0 +1,40 @@ +package main + +import ( + "github.com/go-kratos/kratos/examples/helloworld/helloworld" + "github.com/go-kratos/kratos/v2" + "github.com/go-kratos/kratos/v2/transport/http" +) + +// this example shows how to add middlewares, +// execution order is globalFilter(http) --> routeFilter(http) --> pathFilter(http) --> serviceFilter(service) +func main() { + s := &server{} + httpSrv := http.NewServer( + http.Address(":8000"), + http.Middleware( + // add service filter + serviceMiddleware, + serviceMiddleware2, + ), + // add global filter + http.Filter(globalFilter, globalFilter2), + ) + // register http hanlder to http server + helloworld.RegisterGreeterHTTPServer(httpSrv, s) + + // add route filter + r := httpSrv.Route("/", routeFilter, routeFilter2) + // add path filter to custom route + r.GET("/hello/{name}", sayHelloHandler, pathFilter, pathFilter2) + + app := kratos.New( + kratos.Name("helloworld"), + kratos.Server( + httpSrv, + ), + ) + if err := app.Run(); err != nil { + panic(err) + } +} diff --git a/examples/http/middlewares/middlewares.go b/examples/http/middlewares/middlewares.go new file mode 100644 index 000000000..515f7b438 --- /dev/null +++ b/examples/http/middlewares/middlewares.go @@ -0,0 +1,75 @@ +package main + +import ( + "context" + "fmt" + "net/http" + + "github.com/go-kratos/kratos/v2/middleware" +) + +func globalFilter(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Println("global filter in") + next.ServeHTTP(w, r) + fmt.Println("global filter out") + }) +} + +func globalFilter2(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Println("global filter 2 in") + next.ServeHTTP(w, r) + fmt.Println("global filter 2 out") + }) +} + +func routeFilter(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Println("route filter in") + next.ServeHTTP(w, r) + fmt.Println("route filter out") + }) +} + +func routeFilter2(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Println("route filter 2 in") + next.ServeHTTP(w, r) + fmt.Println("route filter 2 out") + }) +} + +func pathFilter(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Println("path filter in") + next.ServeHTTP(w, r) + fmt.Println("path filter out") + }) +} + +func pathFilter2(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fmt.Println("path filter 2 in") + next.ServeHTTP(w, r) + fmt.Println("path filter 2 out") + }) +} + +func serviceMiddleware(handler middleware.Handler) middleware.Handler { + return func(ctx context.Context, req interface{}) (reply interface{}, err error) { + fmt.Println("service middleware in") + reply, err = handler(ctx, req) + fmt.Println("service middleware out") + return + } +} + +func serviceMiddleware2(handler middleware.Handler) middleware.Handler { + return func(ctx context.Context, req interface{}) (reply interface{}, err error) { + fmt.Println("service middleware 2 in") + reply, err = handler(ctx, req) + fmt.Println("service middleware 2 out") + return + } +} diff --git a/examples/http/middlewares/services.go b/examples/http/middlewares/services.go new file mode 100644 index 000000000..4af9e6888 --- /dev/null +++ b/examples/http/middlewares/services.go @@ -0,0 +1,25 @@ +package main + +import ( + "context" + "fmt" + + "github.com/go-kratos/kratos/examples/helloworld/helloworld" + "github.com/go-kratos/kratos/v2/errors" +) + +// server is used to implement helloworld.GreeterServer. +type server struct { + helloworld.UnimplementedGreeterServer +} + +// SayHello implements helloworld.GreeterServer +func (s *server) SayHello(ctx context.Context, in *helloworld.HelloRequest) (*helloworld.HelloReply, error) { + if in.Name == "error" { + return nil, errors.BadRequest("custom_error", fmt.Sprintf("invalid argument %s", in.Name)) + } + if in.Name == "panic" { + panic("grpc panic") + } + return &helloworld.HelloReply{Message: fmt.Sprintf("Hello %+v", in.Name)}, nil +} diff --git a/examples/http/upload/main.go b/examples/http/upload/main.go index b8960ace5..621d4fdaf 100644 --- a/examples/http/upload/main.go +++ b/examples/http/upload/main.go @@ -1,42 +1,37 @@ package main import ( - "fmt" "io" - "log" - "net/http" "os" "github.com/go-kratos/kratos/v2" - transhttp "github.com/go-kratos/kratos/v2/transport/http" - "github.com/gorilla/mux" + "github.com/go-kratos/kratos/v2/transport/http" ) -func uploadFile(w http.ResponseWriter, r *http.Request) { - fileName := r.FormValue("name") - file, handler, err := r.FormFile("file") +func uploadFile(ctx http.Context) error { + req := ctx.Request() + + fileName := req.FormValue("name") + file, handler, err := req.FormFile("file") if err != nil { - w.WriteHeader(http.StatusInternalServerError) - return + return err } defer file.Close() f, err := os.OpenFile(handler.Filename, os.O_WRONLY|os.O_CREATE, 0666) if err != nil { - w.WriteHeader(http.StatusInternalServerError) - return + return err } defer f.Close() _, _ = io.Copy(f, file) - fmt.Fprint(w, "File "+fileName+" Uploaded successfully") + + return ctx.String(200, "File "+fileName+" Uploaded successfully") } func main() { - router := mux.NewRouter() - router.HandleFunc("/upload", uploadFile).Methods("POST") - - httpSrv := transhttp.NewServer(transhttp.Address(":8000")) - httpSrv.HandlePrefix("/", router) + httpSrv := http.NewServer(http.Address(":8000")) + route := httpSrv.Route("/") + route.POST("/upload", uploadFile) app := kratos.New( kratos.Name("upload"), @@ -45,6 +40,6 @@ func main() { ), ) if err := app.Run(); err != nil { - log.Println(err) + panic(err) } } diff --git a/examples/metadata/server/main.go b/examples/metadata/server/main.go index c5601b559..e10ab5444 100644 --- a/examples/metadata/server/main.go +++ b/examples/metadata/server/main.go @@ -39,25 +39,23 @@ func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloRe func main() { logger := log.NewStdLogger(os.Stdout) - log := log.NewHelper(logger) + s := &server{} grpcSrv := grpc.NewServer( grpc.Address(":9000"), grpc.Middleware( recovery.Recovery(), logging.Server(logger), )) - - s := &server{} - pb.RegisterGreeterServer(grpcSrv, s) - - httpSrv := http.NewServer(http.Address(":8000")) - httpSrv.HandlePrefix("/", pb.NewGreeterHandler(s, + httpSrv := http.NewServer( + http.Address(":8000"), http.Middleware( recovery.Recovery(), logging.Server(logger), - )), + ), ) + pb.RegisterGreeterServer(grpcSrv, s) + pb.RegisterGreeterHTTPServer(httpSrv, s) app := kratos.New( kratos.Name(Name), @@ -68,6 +66,6 @@ func main() { ) if err := app.Run(); err != nil { - log.Error(err) + panic(err) } } diff --git a/examples/proto/echo_service_http.pb.go b/examples/proto/echo_service_http.pb.go deleted file mode 100644 index ea1dfec0d..000000000 --- a/examples/proto/echo_service_http.pb.go +++ /dev/null @@ -1,380 +0,0 @@ -// Code generated by protoc-gen-go-http. DO NOT EDIT. - -package testproto - -import ( - context "context" - middleware "github.com/go-kratos/kratos/v2/middleware" - transport "github.com/go-kratos/kratos/v2/transport" - http1 "github.com/go-kratos/kratos/v2/transport/http" - binding "github.com/go-kratos/kratos/v2/transport/http/binding" - mux "github.com/gorilla/mux" - http "net/http" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the kratos package it is being compiled against. -var _ = new(http.Request) -var _ = new(context.Context) -var _ = new(middleware.Middleware) -var _ = new(transport.Transporter) -var _ = binding.BindVars -var _ = mux.NewRouter - -const _ = http1.SupportPackageIsVersion1 - -type EchoServiceHandler interface { - Echo(context.Context, *SimpleMessage) (*SimpleMessage, error) - - EchoBody(context.Context, *SimpleMessage) (*SimpleMessage, error) - - EchoDelete(context.Context, *SimpleMessage) (*SimpleMessage, error) - - EchoPatch(context.Context, *DynamicMessageUpdate) (*DynamicMessageUpdate, error) - - EchoResponseBody(context.Context, *DynamicMessageUpdate) (*DynamicMessageUpdate, error) -} - -func NewEchoServiceHandler(srv EchoServiceHandler, opts ...http1.HandleOption) http.Handler { - h := http1.DefaultHandleOptions() - for _, o := range opts { - o(&h) - } - r := mux.NewRouter() - - r.HandleFunc("/v1/example/echo/{id}/{num}", func(w http.ResponseWriter, r *http.Request) { - var in SimpleMessage - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return - } - - if err := binding.BindVars(mux.Vars(r), &in); err != nil { - h.Error(w, r, err) - return - } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.Echo(ctx, req.(*SimpleMessage)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/testproto.EchoService/Echo") - out, err := next(ctx, &in) - if err != nil { - h.Error(w, r, err) - return - } - reply := out.(*SimpleMessage) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("GET") - - r.HandleFunc("/v1/example/echo/{id}/{num}/{lang}", func(w http.ResponseWriter, r *http.Request) { - var in SimpleMessage - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return - } - - if err := binding.BindVars(mux.Vars(r), &in); err != nil { - h.Error(w, r, err) - return - } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.Echo(ctx, req.(*SimpleMessage)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/testproto.EchoService/Echo") - out, err := next(ctx, &in) - if err != nil { - h.Error(w, r, err) - return - } - reply := out.(*SimpleMessage) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("GET") - - r.HandleFunc("/v1/example/echo1/{id}/{line_num}/{status.note}", func(w http.ResponseWriter, r *http.Request) { - var in SimpleMessage - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return - } - - if err := binding.BindVars(mux.Vars(r), &in); err != nil { - h.Error(w, r, err) - return - } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.Echo(ctx, req.(*SimpleMessage)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/testproto.EchoService/Echo") - out, err := next(ctx, &in) - if err != nil { - h.Error(w, r, err) - return - } - reply := out.(*SimpleMessage) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("GET") - - r.HandleFunc("/v1/example/echo2/{no.note}", func(w http.ResponseWriter, r *http.Request) { - var in SimpleMessage - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return - } - - if err := binding.BindVars(mux.Vars(r), &in); err != nil { - h.Error(w, r, err) - return - } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.Echo(ctx, req.(*SimpleMessage)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/testproto.EchoService/Echo") - out, err := next(ctx, &in) - if err != nil { - h.Error(w, r, err) - return - } - reply := out.(*SimpleMessage) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("GET") - - r.HandleFunc("/v1/example/echo/{id}", func(w http.ResponseWriter, r *http.Request) { - var in SimpleMessage - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return - } - - if err := binding.BindVars(mux.Vars(r), &in); err != nil { - h.Error(w, r, err) - return - } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.Echo(ctx, req.(*SimpleMessage)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/testproto.EchoService/Echo") - out, err := next(ctx, &in) - if err != nil { - h.Error(w, r, err) - return - } - reply := out.(*SimpleMessage) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("POST") - - r.HandleFunc("/v1/example/echo_body", func(w http.ResponseWriter, r *http.Request) { - var in SimpleMessage - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return - } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.EchoBody(ctx, req.(*SimpleMessage)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/testproto.EchoService/EchoBody") - out, err := next(ctx, &in) - if err != nil { - h.Error(w, r, err) - return - } - reply := out.(*SimpleMessage) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("POST") - - r.HandleFunc("/v1/example/echo_response_body", func(w http.ResponseWriter, r *http.Request) { - var in DynamicMessageUpdate - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return - } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.EchoResponseBody(ctx, req.(*DynamicMessageUpdate)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/testproto.EchoService/EchoResponseBody") - out, err := next(ctx, &in) - if err != nil { - h.Error(w, r, err) - return - } - reply := out.(*DynamicMessageUpdate) - if err := h.Encode(w, r, reply.Body); err != nil { - h.Error(w, r, err) - } - }).Methods("POST") - - r.HandleFunc("/v1/example/echo_delete/{id}/{num}", func(w http.ResponseWriter, r *http.Request) { - var in SimpleMessage - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return - } - - if err := binding.BindVars(mux.Vars(r), &in); err != nil { - h.Error(w, r, err) - return - } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.EchoDelete(ctx, req.(*SimpleMessage)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/testproto.EchoService/EchoDelete") - out, err := next(ctx, &in) - if err != nil { - h.Error(w, r, err) - return - } - reply := out.(*SimpleMessage) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("DELETE") - - r.HandleFunc("/v1/example/echo_patch", func(w http.ResponseWriter, r *http.Request) { - var in DynamicMessageUpdate - if err := h.Decode(r, &in.Body); err != nil { - h.Error(w, r, err) - return - } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.EchoPatch(ctx, req.(*DynamicMessageUpdate)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/testproto.EchoService/EchoPatch") - out, err := next(ctx, &in) - if err != nil { - h.Error(w, r, err) - return - } - reply := out.(*DynamicMessageUpdate) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("PATCH") - - return r -} - -type EchoServiceHTTPClient interface { - Echo(ctx context.Context, req *SimpleMessage, opts ...http1.CallOption) (rsp *SimpleMessage, err error) - - EchoBody(ctx context.Context, req *SimpleMessage, opts ...http1.CallOption) (rsp *SimpleMessage, err error) - - EchoDelete(ctx context.Context, req *SimpleMessage, opts ...http1.CallOption) (rsp *SimpleMessage, err error) - - EchoPatch(ctx context.Context, req *DynamicMessageUpdate, opts ...http1.CallOption) (rsp *DynamicMessageUpdate, err error) - - EchoResponseBody(ctx context.Context, req *DynamicMessageUpdate, opts ...http1.CallOption) (rsp *DynamicMessageUpdate, err error) -} - -type EchoServiceHTTPClientImpl struct { - cc *http1.Client -} - -func NewEchoServiceHTTPClient(client *http1.Client) EchoServiceHTTPClient { - return &EchoServiceHTTPClientImpl{client} -} - -func (c *EchoServiceHTTPClientImpl) Echo(ctx context.Context, in *SimpleMessage, opts ...http1.CallOption) (*SimpleMessage, error) { - var out SimpleMessage - path := binding.EncodePath("POST", "/v1/example/echo/{id}", in) - opts = append(opts, http1.Method("/testproto.EchoService/Echo")) - - err := c.cc.Invoke(ctx, "POST", path, nil, &out, opts...) - - return &out, err -} - -func (c *EchoServiceHTTPClientImpl) EchoBody(ctx context.Context, in *SimpleMessage, opts ...http1.CallOption) (*SimpleMessage, error) { - var out SimpleMessage - path := binding.EncodePath("POST", "/v1/example/echo_body", in) - opts = append(opts, http1.Method("/testproto.EchoService/EchoBody")) - - err := c.cc.Invoke(ctx, "POST", path, in, &out, opts...) - - return &out, err -} - -func (c *EchoServiceHTTPClientImpl) EchoDelete(ctx context.Context, in *SimpleMessage, opts ...http1.CallOption) (*SimpleMessage, error) { - var out SimpleMessage - path := binding.EncodePath("DELETE", "/v1/example/echo_delete/{id}/{num}", in) - opts = append(opts, http1.Method("/testproto.EchoService/EchoDelete")) - - err := c.cc.Invoke(ctx, "DELETE", path, nil, &out, opts...) - - return &out, err -} - -func (c *EchoServiceHTTPClientImpl) EchoPatch(ctx context.Context, in *DynamicMessageUpdate, opts ...http1.CallOption) (*DynamicMessageUpdate, error) { - var out DynamicMessageUpdate - path := binding.EncodePath("PATCH", "/v1/example/echo_patch", in) - opts = append(opts, http1.Method("/testproto.EchoService/EchoPatch")) - - err := c.cc.Invoke(ctx, "PATCH", path, in.Body, &out, opts...) - - return &out, err -} - -func (c *EchoServiceHTTPClientImpl) EchoResponseBody(ctx context.Context, in *DynamicMessageUpdate, opts ...http1.CallOption) (*DynamicMessageUpdate, error) { - var out DynamicMessageUpdate - path := binding.EncodePath("POST", "/v1/example/echo_response_body", in) - opts = append(opts, http1.Method("/testproto.EchoService/EchoResponseBody")) - - err := c.cc.Invoke(ctx, "POST", path, in, &out.Body, opts...) - - return &out, err -} diff --git a/examples/proto/stream.pb.go b/examples/proto/stream.pb.go deleted file mode 100644 index 658d821e9..000000000 --- a/examples/proto/stream.pb.go +++ /dev/null @@ -1,86 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.26.0 -// protoc v3.15.7 -// source: proto/stream.proto - -package testproto - -import ( - _ "google.golang.org/genproto/googleapis/api/annotations" - httpbody "google.golang.org/genproto/googleapis/api/httpbody" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - emptypb "google.golang.org/protobuf/types/known/emptypb" - reflect "reflect" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -var File_proto_stream_proto protoreflect.FileDescriptor - -var file_proto_stream_proto_rawDesc = []byte{ - 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, - 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x62, 0x6f, - 0x64, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x69, 0x0a, 0x0d, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x58, 0x0a, 0x08, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, - 0x61, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x14, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x42, 0x6f, 0x64, 0x79, - 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, - 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x30, 0x01, - 0x42, 0x51, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, - 0x6f, 0x2d, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2f, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2f, - 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, - 0x6f, 0x2d, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, - 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var file_proto_stream_proto_goTypes = []interface{}{ - (*emptypb.Empty)(nil), // 0: google.protobuf.Empty - (*httpbody.HttpBody)(nil), // 1: google.api.HttpBody -} -var file_proto_stream_proto_depIdxs = []int32{ - 0, // 0: testproto.StreamService.Download:input_type -> google.protobuf.Empty - 1, // 1: testproto.StreamService.Download:output_type -> google.api.HttpBody - 1, // [1:2] is the sub-list for method output_type - 0, // [0:1] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_proto_stream_proto_init() } -func file_proto_stream_proto_init() { - if File_proto_stream_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_stream_proto_rawDesc, - NumEnums: 0, - NumMessages: 0, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_proto_stream_proto_goTypes, - DependencyIndexes: file_proto_stream_proto_depIdxs, - }.Build() - File_proto_stream_proto = out.File - file_proto_stream_proto_rawDesc = nil - file_proto_stream_proto_goTypes = nil - file_proto_stream_proto_depIdxs = nil -} diff --git a/examples/registry/consul/server/main.go b/examples/registry/consul/server/main.go index 133f3b512..318b9c348 100644 --- a/examples/registry/consul/server/main.go +++ b/examples/registry/consul/server/main.go @@ -28,12 +28,14 @@ func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloRe func main() { logger := log.NewStdLogger(os.Stdout) - log := log.NewHelper(logger) + consulClient, err := api.NewClient(api.DefaultConfig()) if err != nil { panic(err) } + r := registry.New(consulClient) + s := &server{} grpcSrv := grpc.NewServer( grpc.Address(":9000"), grpc.Middleware( @@ -41,17 +43,15 @@ func main() { logging.Server(logger), ), ) - s := &server{} - pb.RegisterGreeterServer(grpcSrv, s) - - httpSrv := http.NewServer(http.Address(":8000")) - httpSrv.HandlePrefix("/", pb.NewGreeterHandler(s, + httpSrv := http.NewServer( + http.Address(":8000"), http.Middleware( recovery.Recovery(), - )), + ), ) + pb.RegisterGreeterServer(grpcSrv, s) + pb.RegisterGreeterHTTPServer(httpSrv, s) - r := registry.New(consulClient) app := kratos.New( kratos.Name("helloworld"), kratos.Server( @@ -62,6 +62,6 @@ func main() { ) if err := app.Run(); err != nil { - log.Errorf("app run failed:%v", err) + panic(err) } } diff --git a/examples/traces/api/message/message_http.pb.go b/examples/traces/api/message/message_http.pb.go index affc5d465..90aeeb22e 100644 --- a/examples/traces/api/message/message_http.pb.go +++ b/examples/traces/api/message/message_http.pb.go @@ -1,4 +1,6 @@ // Code generated by protoc-gen-go-http. DO NOT EDIT. +// versions: +// protoc-gen-go-http v2.0.0-rc3 package v1 @@ -6,86 +8,69 @@ import ( context "context" middleware "github.com/go-kratos/kratos/v2/middleware" transport "github.com/go-kratos/kratos/v2/transport" - http1 "github.com/go-kratos/kratos/v2/transport/http" + http "github.com/go-kratos/kratos/v2/transport/http" binding "github.com/go-kratos/kratos/v2/transport/http/binding" - mux "github.com/gorilla/mux" - http "net/http" ) // This is a compile-time assertion to ensure that this generated file // is compatible with the kratos package it is being compiled against. -var _ = new(http.Request) var _ = new(context.Context) var _ = new(middleware.Middleware) var _ = new(transport.Transporter) var _ = binding.BindVars -var _ = mux.NewRouter -const _ = http1.SupportPackageIsVersion1 +const _ = http.SupportPackageIsVersion1 -type MessageServiceHandler interface { +type MessageServiceHTTPServer interface { GetUserMessage(context.Context, *GetUserMessageRequest) (*GetUserMessageReply, error) } -func NewMessageServiceHandler(srv MessageServiceHandler, opts ...http1.HandleOption) http.Handler { - h := http1.DefaultHandleOptions() - for _, o := range opts { - o(&h) - } - r := mux.NewRouter() +func RegisterMessageServiceHTTPServer(s *http.Server, srv MessageServiceHTTPServer) { + r := s.Route("/") + r.GET("/v1/message/user/{id}/{count}", _MessageService_GetUserMessage0_HTTP_Handler(srv)) +} - r.HandleFunc("/v1/message/user/{id}/{count}", func(w http.ResponseWriter, r *http.Request) { +func _MessageService_GetUserMessage0_HTTP_Handler(srv MessageServiceHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { var in GetUserMessageRequest - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return + if err := ctx.Bind(&in); err != nil { + return err } - - if err := binding.BindVars(mux.Vars(r), &in); err != nil { - h.Error(w, r, err) - return + if err := binding.BindVars(ctx.Vars(), &in); err != nil { + return err } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { + transport.SetOperation(ctx, "/api.message.v1.MessageService/GetUserMessage") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { return srv.GetUserMessage(ctx, req.(*GetUserMessageRequest)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/api.message.v1.MessageService/GetUserMessage") - out, err := next(ctx, &in) + }) + out, err := h(ctx, &in) if err != nil { - h.Error(w, r, err) - return + return err } reply := out.(*GetUserMessageReply) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("GET") - - return r + return ctx.Result(200, reply) + } } type MessageServiceHTTPClient interface { - GetUserMessage(ctx context.Context, req *GetUserMessageRequest, opts ...http1.CallOption) (rsp *GetUserMessageReply, err error) + GetUserMessage(ctx context.Context, req *GetUserMessageRequest, opts ...http.CallOption) (rsp *GetUserMessageReply, err error) } type MessageServiceHTTPClientImpl struct { - cc *http1.Client + cc *http.Client } -func NewMessageServiceHTTPClient(client *http1.Client) MessageServiceHTTPClient { +func NewMessageServiceHTTPClient(client *http.Client) MessageServiceHTTPClient { return &MessageServiceHTTPClientImpl{client} } -func (c *MessageServiceHTTPClientImpl) GetUserMessage(ctx context.Context, in *GetUserMessageRequest, opts ...http1.CallOption) (*GetUserMessageReply, error) { +func (c *MessageServiceHTTPClientImpl) GetUserMessage(ctx context.Context, in *GetUserMessageRequest, opts ...http.CallOption) (*GetUserMessageReply, error) { var out GetUserMessageReply - path := binding.EncodePath("GET", "/v1/message/user/{id}/{count}", in) - opts = append(opts, http1.Method("/api.message.v1.MessageService/GetUserMessage")) - + path := binding.EncodeVars("/v1/message/user/{id}/{count}", in, true) + opts = append(opts, http.Operation("/api.message.v1.MessageService/GetUserMessage")) err := c.cc.Invoke(ctx, "GET", path, in, &out, opts...) - + if err != nil { + return nil, err + } return &out, err } diff --git a/examples/traces/api/user/user_http.pb.go b/examples/traces/api/user/user_http.pb.go index 5d385cd07..200076fe1 100644 --- a/examples/traces/api/user/user_http.pb.go +++ b/examples/traces/api/user/user_http.pb.go @@ -1,4 +1,6 @@ // Code generated by protoc-gen-go-http. DO NOT EDIT. +// versions: +// protoc-gen-go-http v2.0.0-rc3 package v1 @@ -6,86 +8,69 @@ import ( context "context" middleware "github.com/go-kratos/kratos/v2/middleware" transport "github.com/go-kratos/kratos/v2/transport" - http1 "github.com/go-kratos/kratos/v2/transport/http" + http "github.com/go-kratos/kratos/v2/transport/http" binding "github.com/go-kratos/kratos/v2/transport/http/binding" - mux "github.com/gorilla/mux" - http "net/http" ) // This is a compile-time assertion to ensure that this generated file // is compatible with the kratos package it is being compiled against. -var _ = new(http.Request) var _ = new(context.Context) var _ = new(middleware.Middleware) var _ = new(transport.Transporter) var _ = binding.BindVars -var _ = mux.NewRouter -const _ = http1.SupportPackageIsVersion1 +const _ = http.SupportPackageIsVersion1 -type UserHandler interface { +type UserHTTPServer interface { GetMyMessages(context.Context, *GetMyMessagesRequest) (*GetMyMessagesReply, error) } -func NewUserHandler(srv UserHandler, opts ...http1.HandleOption) http.Handler { - h := http1.DefaultHandleOptions() - for _, o := range opts { - o(&h) - } - r := mux.NewRouter() +func RegisterUserHTTPServer(s *http.Server, srv UserHTTPServer) { + r := s.Route("/") + r.GET("/v1/user/get/message/{count}", _User_GetMyMessages0_HTTP_Handler(srv)) +} - r.HandleFunc("/v1/user/get/message/{count}", func(w http.ResponseWriter, r *http.Request) { +func _User_GetMyMessages0_HTTP_Handler(srv UserHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { var in GetMyMessagesRequest - if err := h.Decode(r, &in); err != nil { - h.Error(w, r, err) - return + if err := ctx.Bind(&in); err != nil { + return err } - - if err := binding.BindVars(mux.Vars(r), &in); err != nil { - h.Error(w, r, err) - return + if err := binding.BindVars(ctx.Vars(), &in); err != nil { + return err } - - next := func(ctx context.Context, req interface{}) (interface{}, error) { + transport.SetOperation(ctx, "/api.user.v1.User/GetMyMessages") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { return srv.GetMyMessages(ctx, req.(*GetMyMessagesRequest)) - } - if h.Middleware != nil { - next = h.Middleware(next) - } - ctx := r.Context() - transport.SetMethod(ctx, "/api.user.v1.User/GetMyMessages") - out, err := next(ctx, &in) + }) + out, err := h(ctx, &in) if err != nil { - h.Error(w, r, err) - return + return err } reply := out.(*GetMyMessagesReply) - if err := h.Encode(w, r, reply); err != nil { - h.Error(w, r, err) - } - }).Methods("GET") - - return r + return ctx.Result(200, reply) + } } type UserHTTPClient interface { - GetMyMessages(ctx context.Context, req *GetMyMessagesRequest, opts ...http1.CallOption) (rsp *GetMyMessagesReply, err error) + GetMyMessages(ctx context.Context, req *GetMyMessagesRequest, opts ...http.CallOption) (rsp *GetMyMessagesReply, err error) } type UserHTTPClientImpl struct { - cc *http1.Client + cc *http.Client } -func NewUserHTTPClient(client *http1.Client) UserHTTPClient { +func NewUserHTTPClient(client *http.Client) UserHTTPClient { return &UserHTTPClientImpl{client} } -func (c *UserHTTPClientImpl) GetMyMessages(ctx context.Context, in *GetMyMessagesRequest, opts ...http1.CallOption) (*GetMyMessagesReply, error) { +func (c *UserHTTPClientImpl) GetMyMessages(ctx context.Context, in *GetMyMessagesRequest, opts ...http.CallOption) (*GetMyMessagesReply, error) { var out GetMyMessagesReply - path := binding.EncodePath("GET", "/v1/user/get/message/{count}", in) - opts = append(opts, http1.Method("/api.user.v1.User/GetMyMessages")) - + path := binding.EncodeVars("/v1/user/get/message/{count}", in, true) + opts = append(opts, http.Operation("/api.user.v1.User/GetMyMessages")) err := c.cc.Invoke(ctx, "GET", path, in, &out, opts...) - + if err != nil { + return nil, err + } return &out, err } diff --git a/examples/traces/app/user/main.go b/examples/traces/app/user/main.go index d08376341..875028ea9 100644 --- a/examples/traces/app/user/main.go +++ b/examples/traces/app/user/main.go @@ -9,7 +9,6 @@ import ( pb "github.com/go-kratos/kratos/examples/traces/api/user" "github.com/go-kratos/kratos/v2" "github.com/go-kratos/kratos/v2/log" - "github.com/go-kratos/kratos/v2/middleware" "github.com/go-kratos/kratos/v2/middleware/logging" "github.com/go-kratos/kratos/v2/middleware/recovery" "github.com/go-kratos/kratos/v2/middleware/tracing" @@ -63,14 +62,15 @@ func (s *server) GetMyMessages(ctx context.Context, in *pb.GetMyMessagesRequest) // create grpc conn conn, err := grpc.DialInsecure(ctx, grpc.WithEndpoint("127.0.0.1:9000"), - grpc.WithMiddleware(middleware.Chain( + grpc.WithMiddleware( + recovery.Recovery(), tracing.Client( tracing.WithTracerProvider(s.tracer), tracing.WithPropagators( propagation.NewCompositeTextMapPropagator(propagation.Baggage{}, propagation.TraceContext{}), ), ), - recovery.Recovery())), + ), grpc.WithTimeout(2*time.Second), ) if err != nil { @@ -100,24 +100,22 @@ func main() { log.Error(err) } - s := &server{tracer: tp} - - httpSrv := http.NewServer(http.Address(":8000")) - httpSrv.HandlePrefix("/", pb.NewUserHandler(s, + httpSrv := http.NewServer( + http.Address(":8000"), http.Middleware( - middleware.Chain( - recovery.Recovery(), - // Configuring tracing middleware - tracing.Server( - tracing.WithTracerProvider(tp), - tracing.WithPropagators( - propagation.NewCompositeTextMapPropagator(propagation.Baggage{}, propagation.TraceContext{}), - ), + recovery.Recovery(), + // Configuring tracing middleware + tracing.Server( + tracing.WithTracerProvider(tp), + tracing.WithPropagators( + propagation.NewCompositeTextMapPropagator(propagation.Baggage{}, propagation.TraceContext{}), ), - logging.Server(logger), ), - )), + logging.Server(logger), + ), ) + s := &server{tracer: tp} + pb.RegisterUserHTTPServer(httpSrv, s) app := kratos.New( kratos.Name(Name), diff --git a/examples/proto/echo_service.pb.go b/internal/testproto/echo_service.pb.go similarity index 54% rename from examples/proto/echo_service.pb.go rename to internal/testproto/echo_service.pb.go index 669731b2b..5ff2d3c82 100644 --- a/examples/proto/echo_service.pb.go +++ b/internal/testproto/echo_service.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go v1.26.0 // protoc v3.15.7 -// source: proto/echo_service.proto +// source: echo_service.proto package testproto @@ -68,11 +68,11 @@ func (x Corpus) String() string { } func (Corpus) Descriptor() protoreflect.EnumDescriptor { - return file_proto_echo_service_proto_enumTypes[0].Descriptor() + return file_echo_service_proto_enumTypes[0].Descriptor() } func (Corpus) Type() protoreflect.EnumType { - return &file_proto_echo_service_proto_enumTypes[0] + return &file_echo_service_proto_enumTypes[0] } func (x Corpus) Number() protoreflect.EnumNumber { @@ -81,7 +81,7 @@ func (x Corpus) Number() protoreflect.EnumNumber { // Deprecated: Use Corpus.Descriptor instead. func (Corpus) EnumDescriptor() ([]byte, []int) { - return file_proto_echo_service_proto_rawDescGZIP(), []int{0} + return file_echo_service_proto_rawDescGZIP(), []int{0} } // Embedded represents a message embedded in SimpleMessage. @@ -99,7 +99,7 @@ type Embedded struct { func (x *Embedded) Reset() { *x = Embedded{} if protoimpl.UnsafeEnabled { - mi := &file_proto_echo_service_proto_msgTypes[0] + mi := &file_echo_service_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -112,7 +112,7 @@ func (x *Embedded) String() string { func (*Embedded) ProtoMessage() {} func (x *Embedded) ProtoReflect() protoreflect.Message { - mi := &file_proto_echo_service_proto_msgTypes[0] + mi := &file_echo_service_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -125,7 +125,7 @@ func (x *Embedded) ProtoReflect() protoreflect.Message { // Deprecated: Use Embedded.ProtoReflect.Descriptor instead. func (*Embedded) Descriptor() ([]byte, []int) { - return file_proto_echo_service_proto_rawDescGZIP(), []int{0} + return file_echo_service_proto_rawDescGZIP(), []int{0} } func (m *Embedded) GetMark() isEmbedded_Mark { @@ -189,7 +189,7 @@ type SimpleMessage struct { func (x *SimpleMessage) Reset() { *x = SimpleMessage{} if protoimpl.UnsafeEnabled { - mi := &file_proto_echo_service_proto_msgTypes[1] + mi := &file_echo_service_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -202,7 +202,7 @@ func (x *SimpleMessage) String() string { func (*SimpleMessage) ProtoMessage() {} func (x *SimpleMessage) ProtoReflect() protoreflect.Message { - mi := &file_proto_echo_service_proto_msgTypes[1] + mi := &file_echo_service_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -215,7 +215,7 @@ func (x *SimpleMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use SimpleMessage.ProtoReflect.Descriptor instead. func (*SimpleMessage) Descriptor() ([]byte, []int) { - return file_proto_echo_service_proto_rawDescGZIP(), []int{1} + return file_echo_service_proto_rawDescGZIP(), []int{1} } func (x *SimpleMessage) GetId() string { @@ -334,7 +334,7 @@ type DynamicMessage struct { func (x *DynamicMessage) Reset() { *x = DynamicMessage{} if protoimpl.UnsafeEnabled { - mi := &file_proto_echo_service_proto_msgTypes[2] + mi := &file_echo_service_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -347,7 +347,7 @@ func (x *DynamicMessage) String() string { func (*DynamicMessage) ProtoMessage() {} func (x *DynamicMessage) ProtoReflect() protoreflect.Message { - mi := &file_proto_echo_service_proto_msgTypes[2] + mi := &file_echo_service_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -360,7 +360,7 @@ func (x *DynamicMessage) ProtoReflect() protoreflect.Message { // Deprecated: Use DynamicMessage.ProtoReflect.Descriptor instead. func (*DynamicMessage) Descriptor() ([]byte, []int) { - return file_proto_echo_service_proto_rawDescGZIP(), []int{2} + return file_echo_service_proto_rawDescGZIP(), []int{2} } func (x *DynamicMessage) GetStructField() *structpb.Struct { @@ -389,7 +389,7 @@ type DynamicMessageUpdate struct { func (x *DynamicMessageUpdate) Reset() { *x = DynamicMessageUpdate{} if protoimpl.UnsafeEnabled { - mi := &file_proto_echo_service_proto_msgTypes[3] + mi := &file_echo_service_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -402,7 +402,7 @@ func (x *DynamicMessageUpdate) String() string { func (*DynamicMessageUpdate) ProtoMessage() {} func (x *DynamicMessageUpdate) ProtoReflect() protoreflect.Message { - mi := &file_proto_echo_service_proto_msgTypes[3] + mi := &file_echo_service_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -415,7 +415,7 @@ func (x *DynamicMessageUpdate) ProtoReflect() protoreflect.Message { // Deprecated: Use DynamicMessageUpdate.ProtoReflect.Descriptor instead. func (*DynamicMessageUpdate) Descriptor() ([]byte, []int) { - return file_proto_echo_service_proto_rawDescGZIP(), []int{3} + return file_echo_service_proto_rawDescGZIP(), []int{3} } func (x *DynamicMessageUpdate) GetBody() *DynamicMessage { @@ -432,129 +432,129 @@ func (x *DynamicMessageUpdate) GetUpdateMask() *fieldmaskpb.FieldMask { return nil } -var File_proto_echo_service_proto protoreflect.FileDescriptor +var File_echo_service_proto protoreflect.FileDescriptor -var file_proto_echo_service_proto_rawDesc = []byte{ - 0x0a, 0x18, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x5f, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x74, 0x65, 0x73, 0x74, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, - 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x46, 0x0a, 0x08, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x12, - 0x1c, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x48, 0x00, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, - 0x04, 0x6e, 0x6f, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6e, - 0x6f, 0x74, 0x65, 0x42, 0x06, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x22, 0x84, 0x02, 0x0a, 0x0d, - 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, - 0x03, 0x6e, 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6e, 0x75, 0x6d, 0x12, - 0x1b, 0x0a, 0x08, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x03, 0x48, 0x00, 0x52, 0x07, 0x6c, 0x69, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x12, 0x14, 0x0a, 0x04, - 0x6c, 0x61, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6c, 0x61, - 0x6e, 0x67, 0x12, 0x2b, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, - 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, - 0x10, 0x0a, 0x02, 0x65, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x48, 0x01, 0x52, 0x02, 0x65, - 0x6e, 0x12, 0x25, 0x0a, 0x02, 0x6e, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, - 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, - 0x65, 0x64, 0x48, 0x01, 0x52, 0x02, 0x6e, 0x6f, 0x12, 0x29, 0x0a, 0x06, 0x63, 0x6f, 0x72, 0x70, - 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x72, 0x70, 0x75, 0x73, 0x52, 0x06, 0x63, 0x6f, 0x72, - 0x70, 0x75, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x42, 0x05, 0x0a, 0x03, 0x65, - 0x78, 0x74, 0x22, 0x85, 0x01, 0x0a, 0x0e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3a, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, - 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x75, 0x63, 0x74, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x46, 0x69, 0x65, 0x6c, - 0x64, 0x12, 0x37, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x82, 0x01, 0x0a, 0x14, 0x44, - 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x12, 0x2d, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x79, - 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x04, 0x62, 0x6f, - 0x64, 0x79, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, - 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, - 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x2a, - 0x5a, 0x0a, 0x06, 0x43, 0x6f, 0x72, 0x70, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x49, - 0x56, 0x45, 0x52, 0x53, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x57, 0x45, 0x42, 0x10, - 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x49, 0x4d, 0x41, 0x47, 0x45, 0x53, 0x10, 0x02, 0x12, 0x09, 0x0a, - 0x05, 0x4c, 0x4f, 0x43, 0x41, 0x4c, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x45, 0x57, 0x53, - 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x52, 0x4f, 0x44, 0x55, 0x43, 0x54, 0x53, 0x10, 0x05, - 0x12, 0x09, 0x0a, 0x05, 0x56, 0x49, 0x44, 0x45, 0x4f, 0x10, 0x06, 0x32, 0xcf, 0x05, 0x0a, 0x0b, - 0x45, 0x63, 0x68, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xf2, 0x01, 0x0a, 0x04, - 0x45, 0x63, 0x68, 0x6f, 0x12, 0x18, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x18, +var file_echo_service_proto_rawDesc = []byte{ + 0x0a, 0x12, 0x65, 0x63, 0x68, 0x6f, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x46, 0x0a, + 0x08, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x08, 0x70, 0x72, 0x6f, + 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x70, + 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, 0x0a, 0x04, 0x6e, 0x6f, 0x74, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x6f, 0x74, 0x65, 0x42, 0x06, 0x0a, + 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x22, 0x84, 0x02, 0x0a, 0x0d, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6e, 0x75, 0x6d, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6e, 0x75, 0x6d, 0x12, 0x1b, 0x0a, 0x08, 0x6c, 0x69, 0x6e, + 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x07, 0x6c, + 0x69, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x12, 0x14, 0x0a, 0x04, 0x6c, 0x61, 0x6e, 0x67, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x6c, 0x61, 0x6e, 0x67, 0x12, 0x2b, 0x0a, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, + 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, + 0x64, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x10, 0x0a, 0x02, 0x65, 0x6e, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x03, 0x48, 0x01, 0x52, 0x02, 0x65, 0x6e, 0x12, 0x25, 0x0a, 0x02, 0x6e, + 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x48, 0x01, 0x52, 0x02, + 0x6e, 0x6f, 0x12, 0x29, 0x0a, 0x06, 0x63, 0x6f, 0x72, 0x70, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, + 0x6f, 0x72, 0x70, 0x75, 0x73, 0x52, 0x06, 0x63, 0x6f, 0x72, 0x70, 0x75, 0x73, 0x42, 0x06, 0x0a, + 0x04, 0x63, 0x6f, 0x64, 0x65, 0x42, 0x05, 0x0a, 0x03, 0x65, 0x78, 0x74, 0x22, 0x85, 0x01, 0x0a, + 0x0e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x3a, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0b, + 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x37, 0x0a, 0x0b, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x22, 0x82, 0x01, 0x0a, 0x14, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x2d, 0x0a, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x65, + 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x3b, 0x0a, 0x0b, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x2a, 0x5a, 0x0a, 0x06, 0x43, 0x6f, 0x72, + 0x70, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x49, 0x56, 0x45, 0x52, 0x53, 0x41, 0x4c, + 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x57, 0x45, 0x42, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x49, + 0x4d, 0x41, 0x47, 0x45, 0x53, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x4c, 0x4f, 0x43, 0x41, 0x4c, + 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x45, 0x57, 0x53, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, + 0x50, 0x52, 0x4f, 0x44, 0x55, 0x43, 0x54, 0x53, 0x10, 0x05, 0x12, 0x09, 0x0a, 0x05, 0x56, 0x49, + 0x44, 0x45, 0x4f, 0x10, 0x06, 0x32, 0xcf, 0x05, 0x0a, 0x0b, 0x45, 0x63, 0x68, 0x6f, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xf2, 0x01, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x18, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, - 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xb5, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0xae, 0x01, 0x22, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, - 0x65, 0x63, 0x68, 0x6f, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x5a, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, - 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x2f, 0x7b, 0x69, - 0x64, 0x7d, 0x2f, 0x7b, 0x6e, 0x75, 0x6d, 0x7d, 0x5a, 0x24, 0x12, 0x22, 0x2f, 0x76, 0x31, 0x2f, - 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x2f, 0x7b, 0x69, 0x64, - 0x7d, 0x2f, 0x7b, 0x6e, 0x75, 0x6d, 0x7d, 0x2f, 0x7b, 0x6c, 0x61, 0x6e, 0x67, 0x7d, 0x5a, 0x31, - 0x12, 0x2f, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x65, 0x63, - 0x68, 0x6f, 0x31, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x7b, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6e, - 0x75, 0x6d, 0x7d, 0x2f, 0x7b, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x6e, 0x6f, 0x74, 0x65, - 0x7d, 0x5a, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, - 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x32, 0x2f, 0x7b, 0x6e, 0x6f, 0x2e, 0x6e, 0x6f, 0x74, 0x65, 0x7d, - 0x12, 0x60, 0x0a, 0x08, 0x45, 0x63, 0x68, 0x6f, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x18, 0x2e, 0x74, - 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x4d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x18, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x22, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, - 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x3a, - 0x01, 0x2a, 0x12, 0x85, 0x01, 0x0a, 0x10, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x1f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x1a, 0x1f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x29, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x65, - 0x63, 0x68, 0x6f, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x62, 0x6f, 0x64, - 0x79, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x6c, 0x0a, 0x0a, 0x45, 0x63, - 0x68, 0x6f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x18, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, + 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x18, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x1a, 0x18, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, - 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2a, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x24, 0x2a, 0x22, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, - 0x65, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x2f, 0x7b, 0x69, - 0x64, 0x7d, 0x2f, 0x7b, 0x6e, 0x75, 0x6d, 0x7d, 0x12, 0x73, 0x0a, 0x09, 0x45, 0x63, 0x68, 0x6f, - 0x50, 0x61, 0x74, 0x63, 0x68, 0x12, 0x1f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x1a, 0x1f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x32, - 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x65, 0x63, 0x68, - 0x6f, 0x5f, 0x70, 0x61, 0x74, 0x63, 0x68, 0x3a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x42, 0x51, 0x5a, - 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x2d, 0x6b, - 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2f, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2f, 0x63, 0x6d, 0x64, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2d, 0x68, - 0x74, 0x74, 0x70, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, - 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x67, 0x65, 0x22, 0xb5, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0xae, 0x01, 0x22, 0x15, 0x2f, 0x76, + 0x31, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x2f, 0x7b, + 0x69, 0x64, 0x7d, 0x5a, 0x1d, 0x12, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x7b, 0x6e, 0x75, + 0x6d, 0x7d, 0x5a, 0x24, 0x12, 0x22, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x7b, 0x6e, 0x75, 0x6d, + 0x7d, 0x2f, 0x7b, 0x6c, 0x61, 0x6e, 0x67, 0x7d, 0x5a, 0x31, 0x12, 0x2f, 0x2f, 0x76, 0x31, 0x2f, + 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x31, 0x2f, 0x7b, 0x69, + 0x64, 0x7d, 0x2f, 0x7b, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x7d, 0x2f, 0x7b, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x6e, 0x6f, 0x74, 0x65, 0x7d, 0x5a, 0x1d, 0x12, 0x1b, 0x2f, + 0x76, 0x31, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x32, + 0x2f, 0x7b, 0x6e, 0x6f, 0x2e, 0x6e, 0x6f, 0x74, 0x65, 0x7d, 0x12, 0x60, 0x0a, 0x08, 0x45, 0x63, + 0x68, 0x6f, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x18, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x1a, 0x18, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x6d, + 0x70, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x1a, 0x22, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, + 0x65, 0x63, 0x68, 0x6f, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x3a, 0x01, 0x2a, 0x12, 0x85, 0x01, 0x0a, + 0x10, 0x45, 0x63, 0x68, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x6f, 0x64, + 0x79, 0x12, 0x1f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x79, + 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x1a, 0x1f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, + 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x22, 0x1e, 0x2f, 0x76, 0x31, + 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x5f, 0x72, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x3a, 0x01, 0x2a, 0x62, 0x04, + 0x62, 0x6f, 0x64, 0x79, 0x12, 0x6c, 0x0a, 0x0a, 0x45, 0x63, 0x68, 0x6f, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x12, 0x18, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, + 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x18, 0x2e, 0x74, + 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x2a, 0x22, + 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x65, 0x63, 0x68, 0x6f, + 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x7b, 0x6e, 0x75, + 0x6d, 0x7d, 0x12, 0x73, 0x0a, 0x09, 0x45, 0x63, 0x68, 0x6f, 0x50, 0x61, 0x74, 0x63, 0x68, 0x12, + 0x1f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x79, 0x6e, 0x61, + 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x1a, 0x1f, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x79, 0x6e, + 0x61, 0x6d, 0x69, 0x63, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x32, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x65, + 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, 0x65, 0x63, 0x68, 0x6f, 0x5f, 0x70, 0x61, 0x74, 0x63, + 0x68, 0x3a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x42, 0x51, 0x5a, 0x4f, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x2d, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2f, + 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2d, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x3b, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( - file_proto_echo_service_proto_rawDescOnce sync.Once - file_proto_echo_service_proto_rawDescData = file_proto_echo_service_proto_rawDesc + file_echo_service_proto_rawDescOnce sync.Once + file_echo_service_proto_rawDescData = file_echo_service_proto_rawDesc ) -func file_proto_echo_service_proto_rawDescGZIP() []byte { - file_proto_echo_service_proto_rawDescOnce.Do(func() { - file_proto_echo_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_echo_service_proto_rawDescData) +func file_echo_service_proto_rawDescGZIP() []byte { + file_echo_service_proto_rawDescOnce.Do(func() { + file_echo_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_echo_service_proto_rawDescData) }) - return file_proto_echo_service_proto_rawDescData + return file_echo_service_proto_rawDescData } -var file_proto_echo_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_proto_echo_service_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_proto_echo_service_proto_goTypes = []interface{}{ +var file_echo_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_echo_service_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_echo_service_proto_goTypes = []interface{}{ (Corpus)(0), // 0: testproto.Corpus (*Embedded)(nil), // 1: testproto.Embedded (*SimpleMessage)(nil), // 2: testproto.SimpleMessage @@ -564,7 +564,7 @@ var file_proto_echo_service_proto_goTypes = []interface{}{ (*structpb.Value)(nil), // 6: google.protobuf.Value (*fieldmaskpb.FieldMask)(nil), // 7: google.protobuf.FieldMask } -var file_proto_echo_service_proto_depIdxs = []int32{ +var file_echo_service_proto_depIdxs = []int32{ 1, // 0: testproto.SimpleMessage.status:type_name -> testproto.Embedded 1, // 1: testproto.SimpleMessage.no:type_name -> testproto.Embedded 0, // 2: testproto.SimpleMessage.corpus:type_name -> testproto.Corpus @@ -589,13 +589,13 @@ var file_proto_echo_service_proto_depIdxs = []int32{ 0, // [0:7] is the sub-list for field type_name } -func init() { file_proto_echo_service_proto_init() } -func file_proto_echo_service_proto_init() { - if File_proto_echo_service_proto != nil { +func init() { file_echo_service_proto_init() } +func file_echo_service_proto_init() { + if File_echo_service_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_proto_echo_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_echo_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Embedded); i { case 0: return &v.state @@ -607,7 +607,7 @@ func file_proto_echo_service_proto_init() { return nil } } - file_proto_echo_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_echo_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SimpleMessage); i { case 0: return &v.state @@ -619,7 +619,7 @@ func file_proto_echo_service_proto_init() { return nil } } - file_proto_echo_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_echo_service_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DynamicMessage); i { case 0: return &v.state @@ -631,7 +631,7 @@ func file_proto_echo_service_proto_init() { return nil } } - file_proto_echo_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_echo_service_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DynamicMessageUpdate); i { case 0: return &v.state @@ -644,11 +644,11 @@ func file_proto_echo_service_proto_init() { } } } - file_proto_echo_service_proto_msgTypes[0].OneofWrappers = []interface{}{ + file_echo_service_proto_msgTypes[0].OneofWrappers = []interface{}{ (*Embedded_Progress)(nil), (*Embedded_Note)(nil), } - file_proto_echo_service_proto_msgTypes[1].OneofWrappers = []interface{}{ + file_echo_service_proto_msgTypes[1].OneofWrappers = []interface{}{ (*SimpleMessage_LineNum)(nil), (*SimpleMessage_Lang)(nil), (*SimpleMessage_En)(nil), @@ -658,19 +658,19 @@ func file_proto_echo_service_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_proto_echo_service_proto_rawDesc, + RawDescriptor: file_echo_service_proto_rawDesc, NumEnums: 1, NumMessages: 4, NumExtensions: 0, NumServices: 1, }, - GoTypes: file_proto_echo_service_proto_goTypes, - DependencyIndexes: file_proto_echo_service_proto_depIdxs, - EnumInfos: file_proto_echo_service_proto_enumTypes, - MessageInfos: file_proto_echo_service_proto_msgTypes, + GoTypes: file_echo_service_proto_goTypes, + DependencyIndexes: file_echo_service_proto_depIdxs, + EnumInfos: file_echo_service_proto_enumTypes, + MessageInfos: file_echo_service_proto_msgTypes, }.Build() - File_proto_echo_service_proto = out.File - file_proto_echo_service_proto_rawDesc = nil - file_proto_echo_service_proto_goTypes = nil - file_proto_echo_service_proto_depIdxs = nil + File_echo_service_proto = out.File + file_echo_service_proto_rawDesc = nil + file_echo_service_proto_goTypes = nil + file_echo_service_proto_depIdxs = nil } diff --git a/examples/proto/echo_service.proto b/internal/testproto/echo_service.proto similarity index 100% rename from examples/proto/echo_service.proto rename to internal/testproto/echo_service.proto diff --git a/examples/proto/echo_service_grpc.pb.go b/internal/testproto/echo_service_grpc.pb.go similarity index 99% rename from examples/proto/echo_service_grpc.pb.go rename to internal/testproto/echo_service_grpc.pb.go index 6174691b0..23374bdcd 100644 --- a/examples/proto/echo_service_grpc.pb.go +++ b/internal/testproto/echo_service_grpc.pb.go @@ -257,5 +257,5 @@ var EchoService_ServiceDesc = grpc.ServiceDesc{ }, }, Streams: []grpc.StreamDesc{}, - Metadata: "proto/echo_service.proto", + Metadata: "echo_service.proto", } diff --git a/internal/testproto/echo_service_http.pb.go b/internal/testproto/echo_service_http.pb.go new file mode 100644 index 000000000..d4162362a --- /dev/null +++ b/internal/testproto/echo_service_http.pb.go @@ -0,0 +1,303 @@ +// Code generated by protoc-gen-go-http. DO NOT EDIT. +// versions: +// protoc-gen-go-http v2.0.0-rc3 + +package testproto + +import ( + context "context" + middleware "github.com/go-kratos/kratos/v2/middleware" + transport "github.com/go-kratos/kratos/v2/transport" + http "github.com/go-kratos/kratos/v2/transport/http" + binding "github.com/go-kratos/kratos/v2/transport/http/binding" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the kratos package it is being compiled against. +var _ = new(context.Context) +var _ = new(middleware.Middleware) +var _ = new(transport.Transporter) +var _ = binding.BindVars + +const _ = http.SupportPackageIsVersion1 + +type EchoServiceHTTPServer interface { + Echo(context.Context, *SimpleMessage) (*SimpleMessage, error) + EchoBody(context.Context, *SimpleMessage) (*SimpleMessage, error) + EchoDelete(context.Context, *SimpleMessage) (*SimpleMessage, error) + EchoPatch(context.Context, *DynamicMessageUpdate) (*DynamicMessageUpdate, error) + EchoResponseBody(context.Context, *DynamicMessageUpdate) (*DynamicMessageUpdate, error) +} + +func RegisterEchoServiceHTTPServer(s *http.Server, srv EchoServiceHTTPServer) { + r := s.Route("/") + r.GET("/v1/example/echo/{id}/{num}", _EchoService_Echo0_HTTP_Handler(srv)) + r.GET("/v1/example/echo/{id}/{num}/{lang}", _EchoService_Echo1_HTTP_Handler(srv)) + r.GET("/v1/example/echo1/{id}/{line_num}/{status.note}", _EchoService_Echo2_HTTP_Handler(srv)) + r.GET("/v1/example/echo2/{no.note}", _EchoService_Echo3_HTTP_Handler(srv)) + r.POST("/v1/example/echo/{id}", _EchoService_Echo4_HTTP_Handler(srv)) + r.POST("/v1/example/echo_body", _EchoService_EchoBody0_HTTP_Handler(srv)) + r.POST("/v1/example/echo_response_body", _EchoService_EchoResponseBody0_HTTP_Handler(srv)) + r.DELETE("/v1/example/echo_delete/{id}/{num}", _EchoService_EchoDelete0_HTTP_Handler(srv)) + r.PATCH("/v1/example/echo_patch", _EchoService_EchoPatch0_HTTP_Handler(srv)) +} + +func _EchoService_Echo0_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { + var in SimpleMessage + if err := ctx.Bind(&in); err != nil { + return err + } + if err := binding.BindVars(ctx.Vars(), &in); err != nil { + return err + } + transport.SetOperation(ctx, "/testproto.EchoService/Echo") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.Echo(ctx, req.(*SimpleMessage)) + }) + out, err := h(ctx, &in) + if err != nil { + return err + } + reply := out.(*SimpleMessage) + return ctx.Result(200, reply) + } +} + +func _EchoService_Echo1_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { + var in SimpleMessage + if err := ctx.Bind(&in); err != nil { + return err + } + if err := binding.BindVars(ctx.Vars(), &in); err != nil { + return err + } + transport.SetOperation(ctx, "/testproto.EchoService/Echo") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.Echo(ctx, req.(*SimpleMessage)) + }) + out, err := h(ctx, &in) + if err != nil { + return err + } + reply := out.(*SimpleMessage) + return ctx.Result(200, reply) + } +} + +func _EchoService_Echo2_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { + var in SimpleMessage + if err := ctx.Bind(&in); err != nil { + return err + } + if err := binding.BindVars(ctx.Vars(), &in); err != nil { + return err + } + transport.SetOperation(ctx, "/testproto.EchoService/Echo") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.Echo(ctx, req.(*SimpleMessage)) + }) + out, err := h(ctx, &in) + if err != nil { + return err + } + reply := out.(*SimpleMessage) + return ctx.Result(200, reply) + } +} + +func _EchoService_Echo3_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { + var in SimpleMessage + if err := ctx.Bind(&in); err != nil { + return err + } + if err := binding.BindVars(ctx.Vars(), &in); err != nil { + return err + } + transport.SetOperation(ctx, "/testproto.EchoService/Echo") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.Echo(ctx, req.(*SimpleMessage)) + }) + out, err := h(ctx, &in) + if err != nil { + return err + } + reply := out.(*SimpleMessage) + return ctx.Result(200, reply) + } +} + +func _EchoService_Echo4_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { + var in SimpleMessage + if err := ctx.Bind(&in); err != nil { + return err + } + if err := binding.BindVars(ctx.Vars(), &in); err != nil { + return err + } + transport.SetOperation(ctx, "/testproto.EchoService/Echo") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.Echo(ctx, req.(*SimpleMessage)) + }) + out, err := h(ctx, &in) + if err != nil { + return err + } + reply := out.(*SimpleMessage) + return ctx.Result(200, reply) + } +} + +func _EchoService_EchoBody0_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { + var in SimpleMessage + if err := ctx.Bind(&in); err != nil { + return err + } + transport.SetOperation(ctx, "/testproto.EchoService/EchoBody") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.EchoBody(ctx, req.(*SimpleMessage)) + }) + out, err := h(ctx, &in) + if err != nil { + return err + } + reply := out.(*SimpleMessage) + return ctx.Result(200, reply) + } +} + +func _EchoService_EchoResponseBody0_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { + var in DynamicMessageUpdate + if err := ctx.Bind(&in); err != nil { + return err + } + transport.SetOperation(ctx, "/testproto.EchoService/EchoResponseBody") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.EchoResponseBody(ctx, req.(*DynamicMessageUpdate)) + }) + out, err := h(ctx, &in) + if err != nil { + return err + } + reply := out.(*DynamicMessageUpdate) + return ctx.Result(200, reply.Body) + } +} + +func _EchoService_EchoDelete0_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { + var in SimpleMessage + if err := ctx.Bind(&in); err != nil { + return err + } + if err := binding.BindVars(ctx.Vars(), &in); err != nil { + return err + } + transport.SetOperation(ctx, "/testproto.EchoService/EchoDelete") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.EchoDelete(ctx, req.(*SimpleMessage)) + }) + out, err := h(ctx, &in) + if err != nil { + return err + } + reply := out.(*SimpleMessage) + return ctx.Result(200, reply) + } +} + +func _EchoService_EchoPatch0_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Context) error { + return func(ctx http.Context) error { + var in DynamicMessageUpdate + if err := ctx.Bind(&in.Body); err != nil { + return err + } + transport.SetOperation(ctx, "/testproto.EchoService/EchoPatch") + h := ctx.Middleware(func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.EchoPatch(ctx, req.(*DynamicMessageUpdate)) + }) + out, err := h(ctx, &in) + if err != nil { + return err + } + reply := out.(*DynamicMessageUpdate) + return ctx.Result(200, reply) + } +} + +type EchoServiceHTTPClient interface { + Echo(ctx context.Context, req *SimpleMessage, opts ...http.CallOption) (rsp *SimpleMessage, err error) + EchoBody(ctx context.Context, req *SimpleMessage, opts ...http.CallOption) (rsp *SimpleMessage, err error) + EchoDelete(ctx context.Context, req *SimpleMessage, opts ...http.CallOption) (rsp *SimpleMessage, err error) + EchoPatch(ctx context.Context, req *DynamicMessageUpdate, opts ...http.CallOption) (rsp *DynamicMessageUpdate, err error) + EchoResponseBody(ctx context.Context, req *DynamicMessageUpdate, opts ...http.CallOption) (rsp *DynamicMessageUpdate, err error) +} + +type EchoServiceHTTPClientImpl struct { + cc *http.Client +} + +func NewEchoServiceHTTPClient(client *http.Client) EchoServiceHTTPClient { + return &EchoServiceHTTPClientImpl{client} +} + +func (c *EchoServiceHTTPClientImpl) Echo(ctx context.Context, in *SimpleMessage, opts ...http.CallOption) (*SimpleMessage, error) { + var out SimpleMessage + path := binding.EncodeVars("/v1/example/echo/{id}", in, false) + opts = append(opts, http.Operation("/testproto.EchoService/Echo")) + err := c.cc.Invoke(ctx, "POST", path, nil, &out, opts...) + if err != nil { + return nil, err + } + return &out, err +} + +func (c *EchoServiceHTTPClientImpl) EchoBody(ctx context.Context, in *SimpleMessage, opts ...http.CallOption) (*SimpleMessage, error) { + var out SimpleMessage + path := binding.EncodeVars("/v1/example/echo_body", in, false) + opts = append(opts, http.Operation("/testproto.EchoService/EchoBody")) + err := c.cc.Invoke(ctx, "POST", path, in, &out, opts...) + if err != nil { + return nil, err + } + return &out, err +} + +func (c *EchoServiceHTTPClientImpl) EchoDelete(ctx context.Context, in *SimpleMessage, opts ...http.CallOption) (*SimpleMessage, error) { + var out SimpleMessage + path := binding.EncodeVars("/v1/example/echo_delete/{id}/{num}", in, false) + opts = append(opts, http.Operation("/testproto.EchoService/EchoDelete")) + err := c.cc.Invoke(ctx, "DELETE", path, nil, &out, opts...) + if err != nil { + return nil, err + } + return &out, err +} + +func (c *EchoServiceHTTPClientImpl) EchoPatch(ctx context.Context, in *DynamicMessageUpdate, opts ...http.CallOption) (*DynamicMessageUpdate, error) { + var out DynamicMessageUpdate + path := binding.EncodeVars("/v1/example/echo_patch", in, false) + opts = append(opts, http.Operation("/testproto.EchoService/EchoPatch")) + err := c.cc.Invoke(ctx, "PATCH", path, in.Body, &out, opts...) + if err != nil { + return nil, err + } + return &out, err +} + +func (c *EchoServiceHTTPClientImpl) EchoResponseBody(ctx context.Context, in *DynamicMessageUpdate, opts ...http.CallOption) (*DynamicMessageUpdate, error) { + var out DynamicMessageUpdate + path := binding.EncodeVars("/v1/example/echo_response_body", in, false) + opts = append(opts, http.Operation("/testproto.EchoService/EchoResponseBody")) + err := c.cc.Invoke(ctx, "POST", path, in, &out.Body, opts...) + if err != nil { + return nil, err + } + return &out, err +} diff --git a/examples/proto/echo_service_test.go b/internal/testproto/echo_service_test.go similarity index 62% rename from examples/proto/echo_service_test.go rename to internal/testproto/echo_service_test.go index 8b3925511..3621cfc3c 100644 --- a/examples/proto/echo_service_test.go +++ b/internal/testproto/echo_service_test.go @@ -2,21 +2,32 @@ package testproto import ( context "context" + "errors" "fmt" - "net" - http "net/http" "testing" "time" "github.com/go-kratos/kratos/v2/encoding" - tr "github.com/go-kratos/kratos/v2/transport/http" + "github.com/go-kratos/kratos/v2/metadata" + "github.com/go-kratos/kratos/v2/transport" + "github.com/go-kratos/kratos/v2/transport/grpc" + "github.com/go-kratos/kratos/v2/transport/http" + _struct "github.com/golang/protobuf/ptypes/struct" + grpcmd "google.golang.org/grpc/metadata" ) +var md = metadata.Metadata{"test_key": "test_value"} + type echoService struct { + UnimplementedEchoServiceServer } func (s *echoService) Echo(ctx context.Context, m *SimpleMessage) (*SimpleMessage, error) { + md := transport.Metadata(ctx) + if v := md.Get("test_key"); v != "test_value" { + return nil, errors.New("md not match" + v) + } return m, nil } @@ -42,7 +53,7 @@ type echoClient struct { // post: /v1/example/echo/{id} func (c *echoClient) Echo(ctx context.Context, in *SimpleMessage) (out *SimpleMessage, err error) { - return c.client.Echo(ctx, in) + return c.client.Echo(ctx, in, http.Metadata(md)) } // post: /v1/example/echo_body @@ -65,25 +76,47 @@ func (c *echoClient) EchoResponseBody(ctx context.Context, in *DynamicMessageUpd return c.client.EchoResponseBody(ctx, in) } -func TestEchoService(t *testing.T) { - s := &echoService{} - h := NewEchoServiceHandler(s) - srv := &http.Server{Addr: ":0", Handler: h} - lis, err := net.Listen("tcp", srv.Addr) +func TestJSON(t *testing.T) { + in := &SimpleMessage{Id: "test_id", Num: 100} + out := &SimpleMessage{} + codec := encoding.GetCodec("json") + data, err := codec.Marshal(in) if err != nil { t.Fatal(err) } - addr := lis.Addr().(*net.TCPAddr) - time.AfterFunc(time.Second, func() { - defer srv.Shutdown(context.Background()) - testEchoClient(t, fmt.Sprintf("127.0.0.1:%d", addr.Port)) - }) - if err := srv.Serve(lis); err != nil && err != http.ErrServerClosed { + if err := codec.Unmarshal(data, out); err != nil { + t.Fatal(err) + } + // body + in2 := &DynamicMessageUpdate{Body: &DynamicMessage{ + ValueField: &_struct.Value{Kind: &_struct.Value_StringValue{StringValue: "test"}}, + }} + out2 := &DynamicMessageUpdate{} + data, err = codec.Marshal(&in2.Body) + if err != nil { + t.Fatal(err) + } + if err := codec.Unmarshal(data, &out2.Body); err != nil { t.Fatal(err) } } -func testEchoClient(t *testing.T, addr string) { +func TestEchoHTTPServer(t *testing.T) { + echo := &echoService{} + ctx := context.Background() + srv := http.NewServer(http.Address(":2333")) + RegisterEchoServiceHTTPServer(srv, echo) + go func() { + if err := srv.Start(ctx); err != nil { + panic(err) + } + }() + time.Sleep(time.Second) + testEchoHTTPClient(t, fmt.Sprintf("127.0.0.1:2333")) + srv.Stop(ctx) +} + +func testEchoHTTPClient(t *testing.T, addr string) { var ( err error in = &SimpleMessage{Id: "test_id", Num: 100} @@ -94,7 +127,7 @@ func testEchoClient(t *testing.T, addr string) { t.Errorf("[%s] expected %v got %v", name, in, out) } } - cc, _ := tr.NewClient(context.Background(), tr.WithEndpoint(addr)) + cc, _ := http.NewClient(context.Background(), http.WithEndpoint(addr)) cli := &echoClient{client: NewEchoServiceHTTPClient(cc)} @@ -137,15 +170,37 @@ func testEchoClient(t *testing.T, addr string) { fmt.Println("echo test success!") } -func TestJSON(t *testing.T) { - in := &SimpleMessage{Id: "test_id", Num: 100} - out := &SimpleMessage{} - codec := encoding.GetCodec("json") - data, err := codec.Marshal(in) +func TestEchoGRPCServer(t *testing.T) { + echo := &echoService{} + ctx := context.Background() + srv := grpc.NewServer(grpc.Address(":2233")) + RegisterEchoServiceServer(srv, echo) + go func() { + if err := srv.Start(ctx); err != nil { + panic(err) + } + }() + time.Sleep(time.Second) + testEchoGRPCClient(t, fmt.Sprintf("127.0.0.1:2233")) + srv.Stop(ctx) +} + +func testEchoGRPCClient(t *testing.T, addr string) { + ctx := context.Background() + cc, err := grpc.DialInsecure(ctx, grpc.WithEndpoint(addr)) if err != nil { t.Fatal(err) } - if err := codec.Unmarshal(data, out); err != nil { + var ( + in = &SimpleMessage{Id: "test_id", Num: 100} + out = &SimpleMessage{} + ) + client := NewEchoServiceClient(cc) + ctx = grpcmd.NewOutgoingContext(ctx, grpcmd.New(md)) + if out, err = client.Echo(ctx, in); err != nil { t.Fatal(err) } + if in.Id != out.Id || in.Num != out.Num { + t.Errorf("expected %v got %v", in, out) + } } diff --git a/internal/testproto/generate.go b/internal/testproto/generate.go new file mode 100644 index 000000000..c0c47a753 --- /dev/null +++ b/internal/testproto/generate.go @@ -0,0 +1,3 @@ +package testproto + +//go:generate protoc --proto_path=. --proto_path=../../third_party --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. --go-http_out=paths=source_relative:. echo_service.proto stream.proto diff --git a/internal/testproto/stream.pb.go b/internal/testproto/stream.pb.go new file mode 100644 index 000000000..7036cf0bb --- /dev/null +++ b/internal/testproto/stream.pb.go @@ -0,0 +1,86 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.15.7 +// source: stream.proto + +package testproto + +import ( + _ "google.golang.org/genproto/googleapis/api/annotations" + httpbody "google.golang.org/genproto/googleapis/api/httpbody" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + emptypb "google.golang.org/protobuf/types/known/emptypb" + reflect "reflect" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +var File_stream_proto protoreflect.FileDescriptor + +var file_stream_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, + 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, + 0x61, 0x70, 0x69, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x62, 0x6f, 0x64, 0x79, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, + 0x69, 0x0a, 0x0d, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x58, 0x0a, 0x08, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x48, 0x74, 0x74, 0x70, 0x42, 0x6f, 0x64, 0x79, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2f, + 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x30, 0x01, 0x42, 0x51, 0x5a, 0x4f, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x2d, 0x6b, 0x72, 0x61, 0x74, + 0x6f, 0x73, 0x2f, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2d, 0x68, 0x74, 0x74, 0x70, + 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x3b, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var file_stream_proto_goTypes = []interface{}{ + (*emptypb.Empty)(nil), // 0: google.protobuf.Empty + (*httpbody.HttpBody)(nil), // 1: google.api.HttpBody +} +var file_stream_proto_depIdxs = []int32{ + 0, // 0: testproto.StreamService.Download:input_type -> google.protobuf.Empty + 1, // 1: testproto.StreamService.Download:output_type -> google.api.HttpBody + 1, // [1:2] is the sub-list for method output_type + 0, // [0:1] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_stream_proto_init() } +func file_stream_proto_init() { + if File_stream_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_stream_proto_rawDesc, + NumEnums: 0, + NumMessages: 0, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_stream_proto_goTypes, + DependencyIndexes: file_stream_proto_depIdxs, + }.Build() + File_stream_proto = out.File + file_stream_proto_rawDesc = nil + file_stream_proto_goTypes = nil + file_stream_proto_depIdxs = nil +} diff --git a/examples/proto/stream.proto b/internal/testproto/stream.proto similarity index 100% rename from examples/proto/stream.proto rename to internal/testproto/stream.proto diff --git a/examples/proto/stream_grpc.pb.go b/internal/testproto/stream_grpc.pb.go similarity index 99% rename from examples/proto/stream_grpc.pb.go rename to internal/testproto/stream_grpc.pb.go index 5f36aacd0..9dfe96f83 100644 --- a/examples/proto/stream_grpc.pb.go +++ b/internal/testproto/stream_grpc.pb.go @@ -126,5 +126,5 @@ var StreamService_ServiceDesc = grpc.ServiceDesc{ ServerStreams: true, }, }, - Metadata: "proto/stream.proto", + Metadata: "stream.proto", } diff --git a/middleware/logging/logging.go b/middleware/logging/logging.go index 65623c47b..af4e6a8c5 100644 --- a/middleware/logging/logging.go +++ b/middleware/logging/logging.go @@ -16,15 +16,15 @@ func Server(logger log.Logger) middleware.Middleware { return func(handler middleware.Handler) middleware.Handler { return func(ctx context.Context, req interface{}) (reply interface{}, err error) { var ( - code int32 - reason string - kind string - method string + code int32 + reason string + kind string + operation string ) startTime := time.Now() if info, ok := transport.FromServerContext(ctx); ok { kind = info.Kind() - method = info.Method() + operation = info.Operation() } reply, err = handler(ctx, req) if se := errors.FromError(err); se != nil { @@ -35,7 +35,7 @@ func Server(logger log.Logger) middleware.Middleware { log.WithContext(ctx, logger).Log(level, "kind", "server", "component", kind, - "method", method, + "operation", operation, "args", extractArgs(req), "code", code, "reason", reason, @@ -52,15 +52,15 @@ func Client(logger log.Logger) middleware.Middleware { return func(handler middleware.Handler) middleware.Handler { return func(ctx context.Context, req interface{}) (reply interface{}, err error) { var ( - code int32 - reason string - kind string - method string + code int32 + reason string + kind string + operation string ) startTime := time.Now() if info, ok := transport.FromClientContext(ctx); ok { kind = info.Kind() - method = info.Method() + operation = info.Operation() } reply, err = handler(ctx, req) if se := errors.FromError(err); se != nil { @@ -71,7 +71,7 @@ func Client(logger log.Logger) middleware.Middleware { log.WithContext(ctx, logger).Log(level, "kind", "client", "component", kind, - "method", method, + "operation", operation, "args", extractArgs(req), "code", code, "reason", reason, diff --git a/middleware/logging/logging_test.go b/middleware/logging/logging_test.go index 335677e89..104c6570c 100644 --- a/middleware/logging/logging_test.go +++ b/middleware/logging/logging_test.go @@ -17,9 +17,9 @@ var ( ) type Transport struct { - kind string - endpoint string - method string + kind string + endpoint string + operation string } func (tr *Transport) Kind() string { @@ -30,12 +30,12 @@ func (tr *Transport) Endpoint() string { return tr.endpoint } -func (tr *Transport) Method() string { - return tr.method +func (tr *Transport) Operation() string { + return tr.operation } -func (tr *Transport) SetMethod(method string) { - tr.method = method +func (tr *Transport) SetOperation(operation string) { + tr.operation = operation } func (tr *Transport) Metadata() metadata.Metadata { @@ -61,21 +61,21 @@ func TestHTTP(t *testing.T) { Server, err, func() context.Context { - return transport.NewServerContext(context.Background(), &Transport{kind: "http", endpoint: "endpoint", method: "/package.service/method"}) + return transport.NewServerContext(context.Background(), &Transport{kind: "http", endpoint: "endpoint", operation: "/package.service/method"}) }(), }, {"http-server@succ", Server, nil, func() context.Context { - return transport.NewServerContext(context.Background(), &Transport{kind: "http", endpoint: "endpoint", method: "/package.service/method"}) + return transport.NewServerContext(context.Background(), &Transport{kind: "http", endpoint: "endpoint", operation: "/package.service/method"}) }(), }, {"http-client@succ", Client, nil, func() context.Context { - return transport.NewClientContext(context.Background(), &Transport{kind: "http", endpoint: "endpoint", method: "/package.service/method"}) + return transport.NewClientContext(context.Background(), &Transport{kind: "http", endpoint: "endpoint", operation: "/package.service/method"}) }(), }, @@ -83,7 +83,7 @@ func TestHTTP(t *testing.T) { Client, err, func() context.Context { - return transport.NewClientContext(context.Background(), &Transport{kind: "http", endpoint: "endpoint", method: "/package.service/method"}) + return transport.NewClientContext(context.Background(), &Transport{kind: "http", endpoint: "endpoint", operation: "/package.service/method"}) }(), }, } diff --git a/middleware/metrics/metrics.go b/middleware/metrics/metrics.go index d7b08e51a..780b9110d 100644 --- a/middleware/metrics/metrics.go +++ b/middleware/metrics/metrics.go @@ -29,9 +29,9 @@ func WithSeconds(c metrics.Observer) Option { } type options struct { - // counter: _requests_code_total{kind, method, code, reason} + // counter: _requests_code_total{kind, operation, code, reason} requests metrics.Counter - // histogram: _requests_seconds_bucket{kind, method} + // histogram: _requests_seconds_bucket{kind, operation} seconds metrics.Observer } @@ -44,15 +44,15 @@ func Server(opts ...Option) middleware.Middleware { return func(handler middleware.Handler) middleware.Handler { return func(ctx context.Context, req interface{}) (interface{}, error) { var ( - code int - reason string - kind string - method string + code int + reason string + kind string + operation string ) startTime := time.Now() if info, ok := transport.FromServerContext(ctx); ok { kind = info.Kind() - method = info.Method() + operation = info.Operation() } reply, err := handler(ctx, req) if se := errors.FromError(err); se != nil { @@ -60,10 +60,10 @@ func Server(opts ...Option) middleware.Middleware { reason = se.Reason } if options.requests != nil { - options.requests.With(kind, method, strconv.Itoa(code), reason).Inc() + options.requests.With(kind, operation, strconv.Itoa(code), reason).Inc() } if options.seconds != nil { - options.seconds.With(kind, method).Observe(time.Since(startTime).Seconds()) + options.seconds.With(kind, operation).Observe(time.Since(startTime).Seconds()) } return reply, err } @@ -79,15 +79,15 @@ func Client(opts ...Option) middleware.Middleware { return func(handler middleware.Handler) middleware.Handler { return func(ctx context.Context, req interface{}) (interface{}, error) { var ( - code int - reason string - kind string - method string + code int + reason string + kind string + operation string ) startTime := time.Now() if info, ok := transport.FromClientContext(ctx); ok { kind = info.Kind() - method = info.Method() + operation = info.Operation() } reply, err := handler(ctx, req) if se := errors.FromError(err); se != nil { @@ -95,10 +95,10 @@ func Client(opts ...Option) middleware.Middleware { reason = se.Reason } if options.requests != nil { - options.requests.With(kind, method, strconv.Itoa(code), reason).Inc() + options.requests.With(kind, operation, strconv.Itoa(code), reason).Inc() } if options.seconds != nil { - options.seconds.With(kind, method).Observe(time.Since(startTime).Seconds()) + options.seconds.With(kind, operation).Observe(time.Since(startTime).Seconds()) } return reply, err } diff --git a/middleware/tracing/tracing.go b/middleware/tracing/tracing.go index ed16b7e91..2b3f385df 100644 --- a/middleware/tracing/tracing.go +++ b/middleware/tracing/tracing.go @@ -38,7 +38,7 @@ func Server(opts ...Option) middleware.Middleware { return func(ctx context.Context, req interface{}) (reply interface{}, err error) { if tr, ok := transport.FromServerContext(ctx); ok { var span trace.Span - ctx, span = tracer.Start(ctx, tr.Kind(), tr.Method(), tr.Metadata()) + ctx, span = tracer.Start(ctx, tr.Kind(), tr.Operation(), tr.Metadata()) defer func() { tracer.End(ctx, span, err) }() } return handler(ctx, req) @@ -53,7 +53,7 @@ func Client(opts ...Option) middleware.Middleware { return func(ctx context.Context, req interface{}) (reply interface{}, err error) { if tr, ok := transport.FromClientContext(ctx); ok { var span trace.Span - ctx, span = tracer.Start(ctx, tr.Kind(), tr.Method(), tr.Metadata()) + ctx, span = tracer.Start(ctx, tr.Kind(), tr.Operation(), tr.Metadata()) defer func() { tracer.End(ctx, span, err) }() } return handler(ctx, req) diff --git a/transport/grpc/client.go b/transport/grpc/client.go index 18af330bf..55d6e7f20 100644 --- a/transport/grpc/client.go +++ b/transport/grpc/client.go @@ -38,7 +38,7 @@ func WithTimeout(timeout time.Duration) ClientOption { // WithMiddleware with client middleware. func WithMiddleware(m ...middleware.Middleware) ClientOption { return func(o *clientOptions) { - o.middleware = middleware.Chain(m...) + o.middleware = m } } @@ -67,8 +67,8 @@ func WithOptions(opts ...grpc.DialOption) ClientOption { type clientOptions struct { endpoint string timeout time.Duration - middleware middleware.Middleware discovery registry.Discovery + middleware []middleware.Middleware ints []grpc.UnaryClientInterceptor grpcOpts []grpc.DialOption } @@ -112,12 +112,12 @@ func dial(ctx context.Context, insecure bool, opts ...ClientOption) (*grpc.Clien return grpc.DialContext(ctx, options.endpoint, grpcOpts...) } -func unaryClientInterceptor(m middleware.Middleware, timeout time.Duration) grpc.UnaryClientInterceptor { +func unaryClientInterceptor(ms []middleware.Middleware, timeout time.Duration) grpc.UnaryClientInterceptor { return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { ctx = transport.NewClientContext(ctx, &Transport{ - endpoint: cc.Target(), - method: method, - metadata: metadata.Metadata{}, + endpoint: cc.Target(), + operation: method, + metadata: metadata.Metadata{}, }) if timeout > 0 { var cancel context.CancelFunc @@ -130,8 +130,8 @@ func unaryClientInterceptor(m middleware.Middleware, timeout time.Duration) grpc } return reply, invoker(ctx, method, req, reply, cc, opts...) } - if m != nil { - h = m(h) + if len(ms) > 0 { + h = middleware.Chain(ms...)(h) } _, err := h(ctx, req) return err diff --git a/transport/grpc/server.go b/transport/grpc/server.go index 74cfe97bc..e6c6bf3af 100644 --- a/transport/grpc/server.go +++ b/transport/grpc/server.go @@ -59,7 +59,7 @@ func Logger(logger log.Logger) ServerOption { // Middleware with server middleware. func Middleware(m ...middleware.Middleware) ServerOption { return func(s *Server) { - s.middleware = middleware.Chain(m...) + s.middleware = m } } @@ -89,7 +89,7 @@ type Server struct { endpoint *url.URL timeout time.Duration log *log.Helper - middleware middleware.Middleware + middleware []middleware.Middleware ints []grpc.UnaryServerInterceptor grpcOpts []grpc.ServerOption health *health.Server @@ -179,9 +179,9 @@ func (s *Server) unaryServerInterceptor() grpc.UnaryServerInterceptor { defer cancel() md, _ := grpcmd.FromIncomingContext(ctx) ctx = transport.NewServerContext(ctx, &Transport{ - endpoint: s.endpoint.String(), - method: info.FullMethod, - metadata: metadata.New(md), + endpoint: s.endpoint.String(), + operation: info.FullMethod, + metadata: metadata.New(md), }) if s.timeout > 0 { var cancel context.CancelFunc @@ -191,8 +191,8 @@ func (s *Server) unaryServerInterceptor() grpc.UnaryServerInterceptor { h := func(ctx context.Context, req interface{}) (interface{}, error) { return handler(ctx, req) } - if s.middleware != nil { - h = s.middleware(h) + if len(s.middleware) > 0 { + h = middleware.Chain(s.middleware...)(h) } return h(ctx, req) } diff --git a/transport/grpc/transport.go b/transport/grpc/transport.go index 91bc3eed0..89bed23bb 100644 --- a/transport/grpc/transport.go +++ b/transport/grpc/transport.go @@ -11,9 +11,9 @@ var ( // Transport is a gRPC transport. type Transport struct { - endpoint string - method string - metadata metadata.Metadata + endpoint string + operation string + metadata metadata.Metadata } // Kind returns the transport kind. @@ -26,14 +26,14 @@ func (tr *Transport) Endpoint() string { return tr.endpoint } -// Method returns the transport method. -func (tr *Transport) Method() string { - return tr.method +// Operation returns the transport operation. +func (tr *Transport) Operation() string { + return tr.operation } -// SetMethod sets the transport method. -func (tr *Transport) SetMethod(method string) { - tr.method = method +// SetOperation sets the transport operation. +func (tr *Transport) SetOperation(operation string) { + tr.operation = operation } // Metadata returns the transport metadata. @@ -43,10 +43,6 @@ func (tr *Transport) Metadata() metadata.Metadata { // WithMetadata with a metadata into transport md. func (tr *Transport) WithMetadata(md metadata.Metadata) { - if tr.metadata == nil { - tr.metadata = md - return - } for k, v := range md { tr.metadata.Set(k, v) } diff --git a/transport/http/binding/bind.go b/transport/http/binding/bind.go index b8f8f4c4c..b16148dad 100644 --- a/transport/http/binding/bind.go +++ b/transport/http/binding/bind.go @@ -18,11 +18,7 @@ func BindForm(req *http.Request, target interface{}) error { } // BindVars bind map parameters to target. -func BindVars(vars map[string]string, target interface{}) error { - values := make(map[string][]string, len(vars)) - for k, v := range vars { - values[k] = []string{v} - } +func BindVars(values map[string][]string, target interface{}) error { if msg, ok := target.(proto.Message); ok { return mapProto(msg, values) } diff --git a/transport/http/binding/encode.go b/transport/http/binding/encode.go index 5aa86b36d..bec790a89 100644 --- a/transport/http/binding/encode.go +++ b/transport/http/binding/encode.go @@ -18,8 +18,8 @@ import ( "google.golang.org/protobuf/types/known/wrapperspb" ) -// EncodePath binds proto message to url path -func EncodePath(method string, pathPattern string, msg proto.Message) string { +// EncodeVars binds proto message to url path +func EncodeVars(pathPattern string, msg proto.Message, isQuery bool) string { if msg == nil || (reflect.ValueOf(msg).Kind() == reflect.Ptr && reflect.ValueOf(msg).IsNil()) { return pathPattern } @@ -40,7 +40,7 @@ func EncodePath(method string, pathPattern string, msg proto.Message) string { } return in }) - if method == "GET" { + if isQuery { u, err := encodeQuery(msg) if err == nil && len(u) > 0 { for key := range pathParams { diff --git a/transport/http/binding/proto_test.go b/transport/http/binding/proto_test.go index 6a828b23e..6018dda7a 100644 --- a/transport/http/binding/proto_test.go +++ b/transport/http/binding/proto_test.go @@ -6,25 +6,25 @@ import ( ) func TestProtoPath(t *testing.T) { - url := EncodePath("POST", "http://helloworld.Greeter/helloworld/{name}/sub/{sub.name}", &HelloRequest{Name: "test", Sub: &Sub{Name: "2233!!!"}}) + url := EncodeVars("http://helloworld.Greeter/helloworld/{name}/sub/{sub.name}", &HelloRequest{Name: "test", Sub: &Sub{Name: "2233!!!"}}, false) fmt.Println(url) if url != `http://helloworld.Greeter/helloworld/test/sub/2233!!!` { t.Fatalf("proto path not expected!actual: %s ", url) } - url = EncodePath("POST", "http://helloworld.Greeter/helloworld/sub", &HelloRequest{Name: "test", Sub: &Sub{Name: "2233!!!"}}) + url = EncodeVars("http://helloworld.Greeter/helloworld/sub", &HelloRequest{Name: "test", Sub: &Sub{Name: "2233!!!"}}, false) fmt.Println(url) if url != `http://helloworld.Greeter/helloworld/sub` { t.Fatalf("proto path not expected!actual: %s ", url) } - url = EncodePath("POST", "http://helloworld.Greeter/helloworld/{name}/sub/{sub.name}", &HelloRequest{Name: "test"}) + url = EncodeVars("http://helloworld.Greeter/helloworld/{name}/sub/{sub.name}", &HelloRequest{Name: "test"}, false) fmt.Println(url) if url != `http://helloworld.Greeter/helloworld/test/sub/` { t.Fatalf("proto path not expected!actual: %s ", url) } - url = EncodePath("POST", "http://helloworld.Greeter/helloworld/{name}/sub/{sub.name33}", &HelloRequest{Name: "test"}) + url = EncodeVars("http://helloworld.Greeter/helloworld/{name}/sub/{sub.name33}", &HelloRequest{Name: "test"}, false) fmt.Println(url) if url != `http://helloworld.Greeter/helloworld/test/sub/{sub.name33}` { t.Fatalf("proto path not expected!actual: %s ", url) diff --git a/transport/http/calloption.go b/transport/http/calloption.go index 840ada85b..b2f6b0432 100644 --- a/transport/http/calloption.go +++ b/transport/http/calloption.go @@ -16,7 +16,7 @@ type CallOption interface { type callInfo struct { contentType string - method string + operation string metatada metadata.Metadata } @@ -49,24 +49,24 @@ func (o ContentTypeCallOption) before(c *callInfo) error { func defaultCallInfo(path string) callInfo { return callInfo{ contentType: "application/json", - method: path, + operation: path, metatada: metadata.Metadata{}, } } -// Method is serviceMethod call option -func Method(method string) CallOption { - return MethodCallOption{Method: method} +// Operation is serviceMethod call option +func Operation(operation string) CallOption { + return OperationCallOption{Operation: operation} } -// MethodCallOption is set ServiceMethod for client call -type MethodCallOption struct { +// OperationCallOption is set ServiceMethod for client call +type OperationCallOption struct { EmptyCallOption - Method string + Operation string } -func (o MethodCallOption) before(c *callInfo) error { - c.method = o.Method +func (o OperationCallOption) before(c *callInfo) error { + c.operation = o.Operation return nil } diff --git a/transport/http/client.go b/transport/http/client.go index 4f5cf6b36..436859d5e 100644 --- a/transport/http/client.go +++ b/transport/http/client.go @@ -44,7 +44,7 @@ type clientOptions struct { transport http.RoundTripper balancer balancer.Balancer discovery registry.Discovery - middleware middleware.Middleware + middleware []middleware.Middleware } // WithTransport with client transport. @@ -71,7 +71,7 @@ func WithUserAgent(ua string) ClientOption { // WithMiddleware with client middleware. func WithMiddleware(m ...middleware.Middleware) ClientOption { return func(o *clientOptions) { - o.middleware = middleware.Chain(m...) + o.middleware = m } } @@ -201,9 +201,11 @@ func (client *Client) Invoke(ctx context.Context, method, path string, args inte c.metatada = metadata.Metadata{} } ctx = transport.NewClientContext(ctx, &Transport{ - endpoint: client.opts.endpoint, - metadata: c.metatada, - method: c.method, + endpoint: client.opts.endpoint, + metadata: c.metatada, + path: path, + method: method, + operation: c.operation, }) return client.invoke(ctx, req, args, reply, c) } @@ -246,8 +248,8 @@ func (client *Client) invoke(ctx context.Context, req *http.Request, args interf } return reply, nil } - if client.opts.middleware != nil { - h = client.opts.middleware(h) + if len(client.opts.middleware) > 0 { + h = middleware.Chain(client.opts.middleware...)(h) } _, err := h(ctx, args) return err diff --git a/transport/http/codec.go b/transport/http/codec.go new file mode 100644 index 000000000..744a7c977 --- /dev/null +++ b/transport/http/codec.go @@ -0,0 +1,89 @@ +package http + +import ( + "io/ioutil" + "net/http" + + "github.com/go-kratos/kratos/v2/encoding" + "github.com/go-kratos/kratos/v2/errors" + "github.com/go-kratos/kratos/v2/internal/httputil" + "github.com/go-kratos/kratos/v2/transport/http/binding" +) + +// SupportPackageIsVersion1 These constants should not be referenced from any other code. +const SupportPackageIsVersion1 = true + +// DecodeRequestFunc is decode request func. +type DecodeRequestFunc func(*http.Request, interface{}) error + +// EncodeResponseFunc is encode response func. +type EncodeResponseFunc func(http.ResponseWriter, *http.Request, interface{}) error + +// EncodeErrorFunc is encode error func. +type EncodeErrorFunc func(http.ResponseWriter, *http.Request, error) + +// DefaultRequestDecoder decodes the request body to object. +func DefaultRequestDecoder(r *http.Request, v interface{}) error { + codec, ok := CodecForRequest(r, "Content-Type") + if ok { + data, err := ioutil.ReadAll(r.Body) + if err != nil { + return errors.BadRequest("CODEC", err.Error()) + } + if err := codec.Unmarshal(data, v); err != nil { + return errors.BadRequest("CODEC", err.Error()) + } + } else { + if err := binding.BindForm(r, v); err != nil { + return errors.BadRequest("CODEC", err.Error()) + } + } + return nil +} + +// DefaultResponseEncoder encodes the object to the HTTP response. +func DefaultResponseEncoder(w http.ResponseWriter, r *http.Request, v interface{}) error { + codec, _ := CodecForRequest(r, "Accept") + data, err := codec.Marshal(v) + if err != nil { + return err + } + w.Header().Set("Content-Type", httputil.ContentType(codec.Name())) + if sc, ok := v.(interface { + StatusCode() int + }); ok { + w.WriteHeader(sc.StatusCode()) + } + _, _ = w.Write(data) + return nil +} + +// DefaultErrorEncoder encodes the error to the HTTP response. +func DefaultErrorEncoder(w http.ResponseWriter, r *http.Request, se error) { + codec, _ := CodecForRequest(r, "Accept") + body, err := codec.Marshal(se) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + w.Header().Set("Content-Type", httputil.ContentType(codec.Name())) + if sc, ok := se.(interface { + StatusCode() int + }); ok { + w.WriteHeader(sc.StatusCode()) + } else { + w.WriteHeader(http.StatusInternalServerError) + } + w.Write(body) +} + +// CodecForRequest get encoding.Codec via http.Request +func CodecForRequest(r *http.Request, name string) (encoding.Codec, bool) { + for _, accept := range r.Header[name] { + codec := encoding.GetCodec(httputil.ContentSubtype(accept)) + if codec != nil { + return codec, true + } + } + return encoding.GetCodec("json"), false +} diff --git a/transport/http/context.go b/transport/http/context.go new file mode 100644 index 000000000..6f74960ab --- /dev/null +++ b/transport/http/context.go @@ -0,0 +1,142 @@ +package http + +import ( + "context" + "encoding/json" + "encoding/xml" + "io" + "net/http" + "net/url" + "time" + + "github.com/go-kratos/kratos/v2/middleware" + "github.com/gorilla/mux" +) + +var _ Context = (*wrapper)(nil) + +// HandlerFunc defines a function to serve HTTP requests. +type HandlerFunc func(Context) error + +// Context is an HTTP Context. +type Context interface { + context.Context + Vars() url.Values + Form() url.Values + Header() http.Header + Request() *http.Request + Response() http.ResponseWriter + Middleware(middleware.Handler) middleware.Handler + Bind(interface{}) error + Returns(interface{}, error) error + Result(int, interface{}) error + JSON(int, interface{}) error + XML(int, interface{}) error + String(int, string) error + Blob(int, string, []byte) error + Stream(int, string, io.Reader) error + Reset(http.ResponseWriter, *http.Request) +} + +type wrapper struct { + route *Route + req *http.Request + res http.ResponseWriter +} + +func (c *wrapper) Header() http.Header { + return c.req.Header +} + +func (c *wrapper) Vars() url.Values { + raws := mux.Vars(c.req) + vars := make(url.Values, len(raws)) + for k, v := range raws { + vars[k] = []string{v} + } + return vars +} +func (c *wrapper) Form() url.Values { + if err := c.req.ParseForm(); err != nil { + return url.Values{} + } + return c.req.Form +} +func (c *wrapper) Request() *http.Request { return c.req } +func (c *wrapper) Response() http.ResponseWriter { return c.res } +func (c *wrapper) Middleware(h middleware.Handler) middleware.Handler { + return middleware.Chain(c.route.srv.ms...)(h) +} +func (c *wrapper) Bind(v interface{}) error { return c.route.srv.dec(c.req, v) } +func (c *wrapper) Returns(v interface{}, err error) error { + if err != nil { + return err + } + if err := c.route.srv.enc(c.res, c.req, v); err != nil { + return err + } + return nil +} +func (c *wrapper) Result(code int, v interface{}) error { + c.res.WriteHeader(code) + if err := c.route.srv.enc(c.res, c.req, v); err != nil { + return err + } + return nil +} +func (c *wrapper) JSON(code int, v interface{}) error { + c.res.WriteHeader(code) + c.res.Header().Set("Content-Type", "application/json") + return json.NewEncoder(c.res).Encode(v) +} +func (c *wrapper) XML(code int, v interface{}) error { + c.res.WriteHeader(code) + c.res.Header().Set("Content-Type", "application/xml") + return xml.NewEncoder(c.res).Encode(v) +} +func (c *wrapper) String(code int, text string) error { + c.res.WriteHeader(code) + c.res.Header().Set("Content-Type", "text/plain") + c.res.Write([]byte(text)) + return nil +} +func (c *wrapper) Blob(code int, contentType string, data []byte) error { + c.res.WriteHeader(code) + c.res.Header().Set("Content-Type", contentType) + c.res.Write(data) + return nil +} +func (c *wrapper) Stream(code int, contentType string, rd io.Reader) error { + c.res.WriteHeader(code) + c.res.Header().Set("Content-Type", contentType) + _, err := io.Copy(c.res, rd) + return err +} +func (c *wrapper) Reset(res http.ResponseWriter, req *http.Request) { + c.res = res + c.req = req +} +func (c *wrapper) Deadline() (time.Time, bool) { + if c.req == nil { + return time.Time{}, false + } + return c.req.Context().Deadline() +} +func (c *wrapper) Done() <-chan struct{} { + if c.req == nil { + return nil + } + return c.req.Context().Done() +} +func (c *wrapper) Err() error { + if c.req == nil { + return context.Canceled + } + return c.req.Context().Err() +} +func (c *wrapper) Value(key interface{}) interface{} { + if c.req == nil { + return nil + } + return c.req.Context().Value(key) +} diff --git a/transport/http/handle.go b/transport/http/handle.go deleted file mode 100644 index 1034a251d..000000000 --- a/transport/http/handle.go +++ /dev/null @@ -1,215 +0,0 @@ -package http - -import ( - "context" - "fmt" - "io/ioutil" - "net/http" - "reflect" - - "github.com/go-kratos/kratos/v2/encoding" - "github.com/go-kratos/kratos/v2/errors" - "github.com/go-kratos/kratos/v2/internal/httputil" - "github.com/go-kratos/kratos/v2/middleware" - "github.com/go-kratos/kratos/v2/transport/http/binding" -) - -// SupportPackageIsVersion1 These constants should not be referenced from any other code. -const SupportPackageIsVersion1 = true - -// DecodeRequestFunc is decode request func. -type DecodeRequestFunc func(*http.Request, interface{}) error - -// EncodeResponseFunc is encode response func. -type EncodeResponseFunc func(http.ResponseWriter, *http.Request, interface{}) error - -// EncodeErrorFunc is encode error func. -type EncodeErrorFunc func(http.ResponseWriter, *http.Request, error) - -// HandleOption is handle option. -type HandleOption func(*HandleOptions) - -// HandleOptions is handle options. -// Deprecated: use Handler instead. -type HandleOptions struct { - Decode DecodeRequestFunc - Encode EncodeResponseFunc - Error EncodeErrorFunc - Middleware middleware.Middleware -} - -// DefaultHandleOptions returns a default handle options. -// Deprecated: use NewHandler instead. -func DefaultHandleOptions() HandleOptions { - return HandleOptions{ - Decode: DefaultRequestDecoder, - Encode: DefaultResponseEncoder, - Error: DefaultErrorEncoder, - } -} - -// RequestDecoder with request decoder. -func RequestDecoder(dec DecodeRequestFunc) HandleOption { - return func(o *HandleOptions) { - o.Decode = dec - } -} - -// ResponseEncoder with response encoder. -func ResponseEncoder(en EncodeResponseFunc) HandleOption { - return func(o *HandleOptions) { - o.Encode = en - } -} - -// ErrorEncoder with error encoder. -func ErrorEncoder(en EncodeErrorFunc) HandleOption { - return func(o *HandleOptions) { - o.Error = en - } -} - -// Middleware with middleware option. -func Middleware(m ...middleware.Middleware) HandleOption { - return func(o *HandleOptions) { - o.Middleware = middleware.Chain(m...) - } -} - -// Handler is handle options. -type Handler struct { - method reflect.Value - in reflect.Type - out reflect.Type - opts HandleOptions -} - -// NewHandler new an HTTP handler. -func NewHandler(handler interface{}, opts ...HandleOption) http.Handler { - if err := validateHandler(handler); err != nil { - panic(err) - } - typ := reflect.TypeOf(handler) - h := &Handler{ - method: reflect.ValueOf(handler), - in: typ.In(1).Elem(), - out: typ.Out(0).Elem(), - opts: DefaultHandleOptions(), - } - for _, o := range opts { - o(&h.opts) - } - return h -} - -func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { - in := reflect.New(h.in).Interface() - if err := h.opts.Decode(req, in); err != nil { - h.opts.Error(w, req, err) - return - } - invoke := func(ctx context.Context, in interface{}) (interface{}, error) { - ret := h.method.Call([]reflect.Value{ - reflect.ValueOf(ctx), - reflect.ValueOf(in), - }) - if ret[1].IsNil() { - return ret[0].Interface(), nil - } - return nil, ret[1].Interface().(error) - } - if h.opts.Middleware != nil { - invoke = h.opts.Middleware(invoke) - } - out, err := invoke(req.Context(), in) - if err != nil { - h.opts.Error(w, req, err) - return - } - if err := h.opts.Encode(w, req, out); err != nil { - h.opts.Error(w, req, err) - } -} - -func validateHandler(handler interface{}) error { - typ := reflect.TypeOf(handler) - if typ.NumIn() != 2 || typ.NumOut() != 2 { - return fmt.Errorf("invalid types, in: %d out: %d", typ.NumIn(), typ.NumOut()) - } - if typ.In(1).Kind() != reflect.Ptr || typ.Out(0).Kind() != reflect.Ptr { - return fmt.Errorf("invalid types is not a pointer") - } - if !typ.In(0).Implements(reflect.TypeOf((*context.Context)(nil)).Elem()) { - return fmt.Errorf("input does not implement the context") - } - if !typ.Out(1).Implements(reflect.TypeOf((*error)(nil)).Elem()) { - return fmt.Errorf("input does not implement the error") - } - return nil -} - -// DefaultRequestDecoder decodes the request body to object. -func DefaultRequestDecoder(r *http.Request, v interface{}) error { - codec, ok := CodecForRequest(r, "Content-Type") - if ok { - data, err := ioutil.ReadAll(r.Body) - if err != nil { - return errors.BadRequest("CODEC", err.Error()) - } - if err := codec.Unmarshal(data, v); err != nil { - return errors.BadRequest("CODEC", err.Error()) - } - } else { - if err := binding.BindForm(r, v); err != nil { - return errors.BadRequest("CODEC", err.Error()) - } - } - return nil -} - -// DefaultResponseEncoder encodes the object to the HTTP response. -func DefaultResponseEncoder(w http.ResponseWriter, r *http.Request, v interface{}) error { - codec, _ := CodecForRequest(r, "Accept") - data, err := codec.Marshal(v) - if err != nil { - return err - } - w.Header().Set("Content-Type", httputil.ContentType(codec.Name())) - if sc, ok := v.(interface { - StatusCode() int - }); ok { - w.WriteHeader(sc.StatusCode()) - } - _, _ = w.Write(data) - return nil -} - -// DefaultErrorEncoder encodes the error to the HTTP response. -func DefaultErrorEncoder(w http.ResponseWriter, r *http.Request, se error) { - codec, _ := CodecForRequest(r, "Accept") - body, err := codec.Marshal(se) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - return - } - w.Header().Set("Content-Type", httputil.ContentType(codec.Name())) - if sc, ok := se.(interface { - StatusCode() int - }); ok { - w.WriteHeader(sc.StatusCode()) - } else { - w.WriteHeader(http.StatusInternalServerError) - } - w.Write(body) -} - -// CodecForRequest get encoding.Codec via http.Request -func CodecForRequest(r *http.Request, name string) (encoding.Codec, bool) { - for _, accept := range r.Header[name] { - codec := encoding.GetCodec(httputil.ContentSubtype(accept)) - if codec != nil { - return codec, true - } - } - return encoding.GetCodec("json"), false -} diff --git a/transport/http/handle_test.go b/transport/http/handle_test.go deleted file mode 100644 index 0165c97d7..000000000 --- a/transport/http/handle_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package http - -import ( - "context" - "testing" -) - -type HelloRequest struct { - Name string `json:"name"` -} -type HelloReply struct { - Message string `json:"message"` -} -type GreeterService struct { -} - -func (s *GreeterService) SayHello(ctx context.Context, req *HelloRequest) (*HelloReply, error) { - return &HelloReply{Message: "hello " + req.Name}, nil -} - -func TestHandler(t *testing.T) { - s := &GreeterService{} - _ = NewHandler(s.SayHello) -} diff --git a/transport/http/route.go b/transport/http/route.go new file mode 100644 index 000000000..aae84fea6 --- /dev/null +++ b/transport/http/route.go @@ -0,0 +1,101 @@ +package http + +import ( + "net/http" + "path" + "sync" +) + +// FilterFunc is a function which receives an http.Handler and returns another http.Handler. +type FilterFunc func(http.Handler) http.Handler + +// FilterChain returns a FilterFunc that specifies the chained handler for HTTP Router. +func FilterChain(filters ...FilterFunc) FilterFunc { + return func(next http.Handler) http.Handler { + for i := len(filters) - 1; i >= 0; i-- { + next = filters[i](next) + } + return next + } +} + +// Route is an HTTP route. +type Route struct { + prefix string + pool sync.Pool + srv *Server + filters []FilterFunc +} + +func newRoute(prefix string, srv *Server, filters ...FilterFunc) *Route { + r := &Route{ + prefix: prefix, + srv: srv, + filters: filters, + } + r.pool.New = func() interface{} { + return &wrapper{route: r} + } + return r +} + +// Handle registers a new route with a matcher for the URL path and method. +func (r *Route) Handle(method, relativePath string, h HandlerFunc, filters ...FilterFunc) { + next := http.Handler(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + ctx := r.pool.Get().(Context) + ctx.Reset(res, req) + if err := h(ctx); err != nil { + r.srv.ene(res, req, err) + } + ctx.Reset(nil, nil) + r.pool.Put(ctx) + })) + next = FilterChain(filters...)(next) + next = FilterChain(r.filters...)(next) + r.srv.router.Handle(path.Join(r.prefix, relativePath), next).Methods(method) +} + +// GET registers a new GET route for a path with matching handler in the router. +func (r *Route) GET(path string, h HandlerFunc, m ...FilterFunc) { + r.Handle(http.MethodGet, path, h, m...) +} + +// HEAD registers a new HEAD route for a path with matching handler in the router. +func (r *Route) HEAD(path string, h HandlerFunc, m ...FilterFunc) { + r.Handle(http.MethodHead, path, h, m...) +} + +// POST registers a new POST route for a path with matching handler in the router. +func (r *Route) POST(path string, h HandlerFunc, m ...FilterFunc) { + r.Handle(http.MethodPost, path, h, m...) +} + +// PUT registers a new PUT route for a path with matching handler in the router. +func (r *Route) PUT(path string, h HandlerFunc, m ...FilterFunc) { + r.Handle(http.MethodPut, path, h, m...) +} + +// PATCH registers a new PATCH route for a path with matching handler in the router. +func (r *Route) PATCH(path string, h HandlerFunc, m ...FilterFunc) { + r.Handle(http.MethodPatch, path, h, m...) +} + +// DELETE registers a new DELETE route for a path with matching handler in the router. +func (r *Route) DELETE(path string, h HandlerFunc, m ...FilterFunc) { + r.Handle(http.MethodDelete, path, h, m...) +} + +// CONNECT registers a new CONNECT route for a path with matching handler in the router. +func (r *Route) CONNECT(path string, h HandlerFunc, m ...FilterFunc) { + r.Handle(http.MethodConnect, path, h, m...) +} + +// OPTIONS registers a new OPTIONS route for a path with matching handler in the router. +func (r *Route) OPTIONS(path string, h HandlerFunc, m ...FilterFunc) { + r.Handle(http.MethodOptions, path, h, m...) +} + +// TRACE registers a new TRACE route for a path with matching handler in the router. +func (r *Route) TRACE(path string, h HandlerFunc, m ...FilterFunc) { + r.Handle(http.MethodTrace, path, h, m...) +} diff --git a/transport/http/route_test.go b/transport/http/route_test.go new file mode 100644 index 000000000..a32b28a6d --- /dev/null +++ b/transport/http/route_test.go @@ -0,0 +1,135 @@ +package http + +import ( + "context" + "encoding/json" + "fmt" + "log" + "net/http" + "strings" + "testing" + "time" + + "github.com/go-kratos/kratos/v2/internal/host" +) + +type User struct { + Name string `json:"name"` +} + +func authFilter(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Do stuff here + log.Println("auth:", r.Method, r.RequestURI) + // Call the next handler, which can be another middleware in the chain, or the final handler. + next.ServeHTTP(w, r) + }) +} +func loggingFilter(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // Do stuff here + log.Println("logging:", r.Method, r.RequestURI) + // Call the next handler, which can be another middleware in the chain, or the final handler. + next.ServeHTTP(w, r) + }) +} + +func TestRoute(t *testing.T) { + ctx := context.Background() + srv := NewServer( + Filter(loggingFilter), + ) + route := srv.Route("/v1") + route.GET("/users/{name}", func(ctx Context) error { + u := new(User) + u.Name = ctx.Vars().Get("name") + return ctx.Result(200, u) + }, authFilter) + route.POST("/users", func(ctx Context) error { + u := new(User) + if err := ctx.Bind(u); err != nil { + return err + } + return ctx.Result(201, u) + }) + route.PUT("/users", func(ctx Context) error { + u := new(User) + if err := ctx.Bind(u); err != nil { + return err + } + h := ctx.Middleware(func(ctx context.Context, in interface{}) (interface{}, error) { + return u, nil + }) + return ctx.Returns(h(ctx, u)) + }) + + if e, err := srv.Endpoint(); err != nil || e == nil { + t.Fatal(e, err) + } + go func() { + if err := srv.Start(ctx); err != nil { + panic(err) + } + }() + time.Sleep(time.Second) + testRoute(t, srv) + srv.Stop(ctx) +} + +func testRoute(t *testing.T, srv *Server) { + port, ok := host.Port(srv.lis) + if !ok { + t.Fatalf("extract port error: %v", srv.lis) + } + base := fmt.Sprintf("http://127.0.0.1:%d/v1", port) + // GET + resp, err := http.Get(base + "/users/foo") + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.StatusCode != 200 { + t.Fatalf("code: %d", resp.StatusCode) + } + u := new(User) + if err := json.NewDecoder(resp.Body).Decode(u); err != nil { + t.Fatal(err) + } + if u.Name != "foo" { + t.Fatalf("got %s want foo", u.Name) + } + // POST + resp, err = http.Post(base+"/users", "application/json", strings.NewReader(`{"name":"bar"}`)) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.StatusCode != 201 { + t.Fatalf("code: %d", resp.StatusCode) + } + u = new(User) + if err = json.NewDecoder(resp.Body).Decode(u); err != nil { + t.Fatal(err) + } + if u.Name != "bar" { + t.Fatalf("got %s want bar", u.Name) + } + // PUT + req, _ := http.NewRequest("PUT", base+"/users", strings.NewReader(`{"name":"bar"}`)) + req.Header.Set("Content-Type", "application/json") + resp, err = http.DefaultClient.Do(req) + if err != nil { + t.Fatal(err) + } + defer resp.Body.Close() + if resp.StatusCode != 200 { + t.Fatalf("code: %d", resp.StatusCode) + } + u = new(User) + if err = json.NewDecoder(resp.Body).Decode(u); err != nil { + t.Fatal(err) + } + if u.Name != "bar" { + t.Fatalf("got %s want bar", u.Name) + } +} diff --git a/transport/http/server.go b/transport/http/server.go index fbe21d2ce..12f7664ce 100644 --- a/transport/http/server.go +++ b/transport/http/server.go @@ -13,6 +13,7 @@ import ( "github.com/go-kratos/kratos/v2/internal/host" "github.com/go-kratos/kratos/v2/log" "github.com/go-kratos/kratos/v2/metadata" + "github.com/go-kratos/kratos/v2/middleware" "github.com/go-kratos/kratos/v2/transport" "github.com/gorilla/mux" @@ -52,17 +53,57 @@ func Logger(logger log.Logger) ServerOption { } } +// Middleware with service middleware option. +func Middleware(m ...middleware.Middleware) ServerOption { + return func(o *Server) { + o.ms = m + } +} + +// Filter with HTTP middleware option. +func Filter(filters ...FilterFunc) ServerOption { + return func(o *Server) { + o.filters = filters + } +} + +// RequestDecoder with request decoder. +func RequestDecoder(dec DecodeRequestFunc) ServerOption { + return func(o *Server) { + o.dec = dec + } +} + +// ResponseEncoder with response encoder. +func ResponseEncoder(en EncodeResponseFunc) ServerOption { + return func(o *Server) { + o.enc = en + } +} + +// ErrorEncoder with error encoder. +func ErrorEncoder(en EncodeErrorFunc) ServerOption { + return func(o *Server) { + o.ene = en + } +} + // Server is an HTTP server wrapper. type Server struct { *http.Server ctx context.Context lis net.Listener once sync.Once + endpoint *url.URL err error network string address string - endpoint *url.URL timeout time.Duration + filters []FilterFunc + ms []middleware.Middleware + dec DecodeRequestFunc + enc EncodeResponseFunc + ene EncodeErrorFunc router *mux.Router log *log.Helper } @@ -73,16 +114,25 @@ func NewServer(opts ...ServerOption) *Server { network: "tcp", address: ":0", timeout: 1 * time.Second, + dec: DefaultRequestDecoder, + enc: DefaultResponseEncoder, + ene: DefaultErrorEncoder, log: log.NewHelper(log.DefaultLogger), } for _, o := range opts { o(srv) } - srv.router = mux.NewRouter() srv.Server = &http.Server{Handler: srv} + srv.router = mux.NewRouter() + srv.router.Use(srv.filter()) return srv } +// Route registers an HTTP route. +func (s *Server) Route(prefix string, filters ...FilterFunc) *Route { + return newRoute(prefix, s, filters...) +} + // Handle registers a new route with a matcher for the URL path. func (s *Server) Handle(path string, h http.Handler) { s.router.Handle(path, h) @@ -100,18 +150,35 @@ func (s *Server) HandleFunc(path string, h http.HandlerFunc) { // ServeHTTP should write reply headers and data to the ResponseWriter and then return. func (s *Server) ServeHTTP(res http.ResponseWriter, req *http.Request) { - ctx, cancel := ic.Merge(req.Context(), s.ctx) - defer cancel() - ctx = transport.NewServerContext(ctx, &Transport{ - endpoint: s.endpoint.String(), - method: req.RequestURI, - metadata: metadata.New(req.Header), - }) - if s.timeout > 0 { - ctx, cancel = context.WithTimeout(ctx, s.timeout) - defer cancel() + s.router.ServeHTTP(res, req) +} + +func (s *Server) filter() mux.MiddlewareFunc { + return func(next http.Handler) http.Handler { + next = FilterChain(s.filters...)(next) + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + ctx, cancel := ic.Merge(req.Context(), s.ctx) + defer cancel() + if s.timeout > 0 { + ctx, cancel = context.WithTimeout(ctx, s.timeout) + defer cancel() + } + tr := &Transport{ + endpoint: s.endpoint.String(), + path: req.RequestURI, + method: req.Method, + operation: req.RequestURI, + metadata: metadata.New(req.Header), + } + if r := mux.CurrentRoute(req); r != nil { + if path, err := r.GetPathTemplate(); err == nil { + tr.operation = path + } + } + ctx = transport.NewServerContext(ctx, tr) + next.ServeHTTP(w, req.WithContext(ctx)) + }) } - s.router.ServeHTTP(res, req.WithContext(ctx)) } // Endpoint return a real address to registry endpoint. diff --git a/transport/http/transport.go b/transport/http/transport.go index e2e3f46dd..8a9eb9bbb 100644 --- a/transport/http/transport.go +++ b/transport/http/transport.go @@ -1,6 +1,8 @@ package http import ( + "context" + "github.com/go-kratos/kratos/v2/metadata" "github.com/go-kratos/kratos/v2/transport" ) @@ -11,9 +13,11 @@ var ( // Transport is an HTTP transport. type Transport struct { - endpoint string - method string - metadata metadata.Metadata + endpoint string + path string + method string + operation string + metadata metadata.Metadata } // Kind returns the transport kind. @@ -26,14 +30,14 @@ func (tr *Transport) Endpoint() string { return tr.endpoint } -// Method returns the transport method. -func (tr *Transport) Method() string { - return tr.method +// Operation returns the transport operation. +func (tr *Transport) Operation() string { + return tr.operation } -// SetMethod sets the transport method. -func (tr *Transport) SetMethod(method string) { - tr.method = method +// SetOperation sets the transport operation. +func (tr *Transport) SetOperation(operation string) { + tr.operation = operation } // Metadata returns the transport metadata. @@ -43,11 +47,27 @@ func (tr *Transport) Metadata() metadata.Metadata { // WithMetadata with a metadata into transport md. func (tr *Transport) WithMetadata(md metadata.Metadata) { - if tr.metadata == nil { - tr.metadata = md - return - } for k, v := range md { tr.metadata.Set(k, v) } } + +// Path returns the Transport path from server context. +func Path(ctx context.Context) string { + if tr, ok := transport.FromServerContext(ctx); ok { + if tr, ok := tr.(*Transport); ok { + return tr.path + } + } + return "" +} + +// Method returns the Transport method from server context. +func Method(ctx context.Context) string { + if tr, ok := transport.FromServerContext(ctx); ok { + if tr, ok := tr.(*Transport); ok { + return tr.method + } + } + return "" +} diff --git a/transport/transport.go b/transport/transport.go index 3e2995a93..3d3ac1137 100644 --- a/transport/transport.go +++ b/transport/transport.go @@ -28,8 +28,8 @@ type Transporter interface { Kind() string Endpoint() string - Method() string - SetMethod(string) + Operation() string + SetOperation(string) Metadata() metadata.Metadata // WithMetadata merge new metadata into transport, @@ -62,19 +62,19 @@ func FromClientContext(ctx context.Context) (tr Transporter, ok bool) { return } -// Method returns the Transport method from server context. -func Method(ctx context.Context) string { +// SetOperation set operation into context transport. +func SetOperation(ctx context.Context, method string) { if tr, ok := FromServerContext(ctx); ok { - return tr.Method() + tr.SetOperation(method) } - return "" } -// SetMethod set serviceMethod into context transport. -func SetMethod(ctx context.Context, method string) { +// Operation returns the Transport operation from server context. +func Operation(ctx context.Context) string { if tr, ok := FromServerContext(ctx); ok { - tr.SetMethod(method) + return tr.Operation() } + return "" } // Metadata returns incoming metadata from server transport. @@ -84,10 +84,3 @@ func Metadata(ctx context.Context) metadata.Metadata { } return metadata.Metadata{} } - -// SetMetadata sets outgoing metadata into client transport. -func SetMetadata(ctx context.Context, md metadata.Metadata) { - if tr, ok := FromClientContext(ctx); ok { - tr.WithMetadata(md) - } -}