add path pattern for http (#1076)

* add path pattern for http
pull/1078/head
longxboy 3 years ago committed by GitHub
parent a50bbbd0d5
commit 8baa2ede4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      api/metadata/metadata_http.pb.go
  2. 2
      cmd/protoc-gen-go-http/main.go
  3. 4
      cmd/protoc-gen-go-http/template.go
  4. 22
      examples/blog/api/blog/v1/blog_http.pb.go
  5. 6
      examples/helloworld/helloworld/helloworld_http.pb.go
  6. 6
      examples/traces/api/message/message_http.pb.go
  7. 6
      examples/traces/api/user/user_http.pb.go
  8. 22
      internal/testproto/echo_service_http.pb.go
  9. 8
      transport/http/binding/encode.go
  10. 26
      transport/http/calloption.go
  11. 9
      transport/http/client.go
  12. 14
      transport/http/server.go
  13. 14
      transport/http/transport.go

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-http. DO NOT EDIT.
// versions:
// protoc-gen-go-http v2.0.0-rc3
// protoc-gen-go-http v2.0.0-rc5
package metadata
@ -84,8 +84,10 @@ func NewMetadataHTTPClient(client *http.Client) MetadataHTTPClient {
func (c *MetadataHTTPClientImpl) GetServiceDesc(ctx context.Context, in *GetServiceDescRequest, opts ...http.CallOption) (*GetServiceDescReply, error) {
var out GetServiceDescReply
path := binding.EncodeURL("/services/{name}", in, true)
pattern := "/services/{name}"
path := binding.EncodeURL(pattern, in, true)
opts = append(opts, http.Operation("/kratos.api.Metadata/GetServiceDesc"))
opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "GET", path, nil, &out, opts...)
if err != nil {
return nil, err
@ -95,8 +97,10 @@ func (c *MetadataHTTPClientImpl) GetServiceDesc(ctx context.Context, in *GetServ
func (c *MetadataHTTPClientImpl) ListServices(ctx context.Context, in *ListServicesRequest, opts ...http.CallOption) (*ListServicesReply, error) {
var out ListServicesReply
path := binding.EncodeURL("/services", in, true)
pattern := "/services"
path := binding.EncodeURL(pattern, in, true)
opts = append(opts, http.Operation("/kratos.api.Metadata/ListServices"))
opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "GET", path, nil, &out, opts...)
if err != nil {
return nil, err

@ -8,7 +8,7 @@ import (
"google.golang.org/protobuf/types/pluginpb"
)
const version = "v2.0.0-rc3"
const version = "v2.0.0-rc5"
func main() {
showVersion := flag.Bool("version", false, "print the version and exit")

@ -65,8 +65,10 @@ func New{{.ServiceType}}HTTPClient (client *http.Client) {{.ServiceType}}HTTPCli
{{range .MethodSets}}
func (c *{{$svrType}}HTTPClientImpl) {{.Name}}(ctx context.Context, in *{{.Request}}, opts ...http.CallOption) (*{{.Reply}}, error) {
var out {{.Reply}}
path := binding.EncodeURL("{{.Path}}", in, {{.IsQuery}})
pattern := "{{.Path}}"
path := binding.EncodeURL(pattern, in, {{.IsQuery}})
opts = append(opts, http.Operation("/{{$svrName}}/{{.Name}}"))
opts = append(opts, http.PathTemplate(pattern))
{{if .HasBody -}}
err := c.cc.Invoke(ctx, "{{.Method}}", path, in{{.Body}}, &out{{.ResponseBody}}, opts...)
{{else -}}

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-http. DO NOT EDIT.
// versions:
// protoc-gen-go-http v2.0.0-rc3
// protoc-gen-go-http v2.0.0-rc5
package v1
@ -156,8 +156,10 @@ func NewBlogServiceHTTPClient(client *http.Client) BlogServiceHTTPClient {
func (c *BlogServiceHTTPClientImpl) CreateArticle(ctx context.Context, in *CreateArticleRequest, opts ...http.CallOption) (*CreateArticleReply, error) {
var out CreateArticleReply
path := binding.EncodeURL("/v1/article/", in, false)
pattern := "/v1/article/"
path := binding.EncodeURL(pattern, in, false)
opts = append(opts, http.Operation("/blog.api.v1.BlogService/CreateArticle"))
opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "POST", path, in, &out, opts...)
if err != nil {
return nil, err
@ -167,8 +169,10 @@ func (c *BlogServiceHTTPClientImpl) CreateArticle(ctx context.Context, in *Creat
func (c *BlogServiceHTTPClientImpl) DeleteArticle(ctx context.Context, in *DeleteArticleRequest, opts ...http.CallOption) (*DeleteArticleReply, error) {
var out DeleteArticleReply
path := binding.EncodeURL("/v1/article/{id}", in, false)
pattern := "/v1/article/{id}"
path := binding.EncodeURL(pattern, in, false)
opts = append(opts, http.Operation("/blog.api.v1.BlogService/DeleteArticle"))
opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "DELETE", path, nil, &out, opts...)
if err != nil {
return nil, err
@ -178,8 +182,10 @@ func (c *BlogServiceHTTPClientImpl) DeleteArticle(ctx context.Context, in *Delet
func (c *BlogServiceHTTPClientImpl) GetArticle(ctx context.Context, in *GetArticleRequest, opts ...http.CallOption) (*GetArticleReply, error) {
var out GetArticleReply
path := binding.EncodeURL("/v1/article/{id}", in, true)
pattern := "/v1/article/{id}"
path := binding.EncodeURL(pattern, in, true)
opts = append(opts, http.Operation("/blog.api.v1.BlogService/GetArticle"))
opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "GET", path, nil, &out, opts...)
if err != nil {
return nil, err
@ -189,8 +195,10 @@ func (c *BlogServiceHTTPClientImpl) GetArticle(ctx context.Context, in *GetArtic
func (c *BlogServiceHTTPClientImpl) ListArticle(ctx context.Context, in *ListArticleRequest, opts ...http.CallOption) (*ListArticleReply, error) {
var out ListArticleReply
path := binding.EncodeURL("/v1/article/", in, true)
pattern := "/v1/article/"
path := binding.EncodeURL(pattern, in, true)
opts = append(opts, http.Operation("/blog.api.v1.BlogService/ListArticle"))
opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "GET", path, nil, &out, opts...)
if err != nil {
return nil, err
@ -200,8 +208,10 @@ func (c *BlogServiceHTTPClientImpl) ListArticle(ctx context.Context, in *ListArt
func (c *BlogServiceHTTPClientImpl) UpdateArticle(ctx context.Context, in *UpdateArticleRequest, opts ...http.CallOption) (*UpdateArticleReply, error) {
var out UpdateArticleReply
path := binding.EncodeURL("/v1/article/{id}", in, false)
pattern := "/v1/article/{id}"
path := binding.EncodeURL(pattern, in, false)
opts = append(opts, http.Operation("/blog.api.v1.BlogService/UpdateArticle"))
opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "PUT", path, in, &out, opts...)
if err != nil {
return nil, err

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-http. DO NOT EDIT.
// versions:
// protoc-gen-go-http v2.0.0-rc3
// protoc-gen-go-http v2.0.0-rc5
package helloworld
@ -62,8 +62,10 @@ func NewGreeterHTTPClient(client *http.Client) GreeterHTTPClient {
func (c *GreeterHTTPClientImpl) SayHello(ctx context.Context, in *HelloRequest, opts ...http.CallOption) (*HelloReply, error) {
var out HelloReply
path := binding.EncodeURL("/helloworld/{name}", in, true)
pattern := "/helloworld/{name}"
path := binding.EncodeURL(pattern, in, true)
opts = append(opts, http.Operation("/helloworld.Greeter/SayHello"))
opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "GET", path, nil, &out, opts...)
if err != nil {
return nil, err

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-http. DO NOT EDIT.
// versions:
// protoc-gen-go-http v2.0.0-rc3
// protoc-gen-go-http v2.0.0-rc5
package v1
@ -62,8 +62,10 @@ func NewMessageServiceHTTPClient(client *http.Client) MessageServiceHTTPClient {
func (c *MessageServiceHTTPClientImpl) GetUserMessage(ctx context.Context, in *GetUserMessageRequest, opts ...http.CallOption) (*GetUserMessageReply, error) {
var out GetUserMessageReply
path := binding.EncodeURL("/v1/message/user/{id}/{count}", in, true)
pattern := "/v1/message/user/{id}/{count}"
path := binding.EncodeURL(pattern, in, true)
opts = append(opts, http.Operation("/api.message.v1.MessageService/GetUserMessage"))
opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "GET", path, in, &out, opts...)
if err != nil {
return nil, err

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-http. DO NOT EDIT.
// versions:
// protoc-gen-go-http v2.0.0-rc3
// protoc-gen-go-http v2.0.0-rc5
package v1
@ -62,8 +62,10 @@ func NewUserHTTPClient(client *http.Client) UserHTTPClient {
func (c *UserHTTPClientImpl) GetMyMessages(ctx context.Context, in *GetMyMessagesRequest, opts ...http.CallOption) (*GetMyMessagesReply, error) {
var out GetMyMessagesReply
path := binding.EncodeURL("/v1/user/get/message/{count}", in, true)
pattern := "/v1/user/get/message/{count}"
path := binding.EncodeURL(pattern, in, true)
opts = append(opts, http.Operation("/api.user.v1.User/GetMyMessages"))
opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "GET", path, in, &out, opts...)
if err != nil {
return nil, err

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go-http. DO NOT EDIT.
// versions:
// protoc-gen-go-http v2.0.0-rc3
// protoc-gen-go-http v2.0.0-rc5
package testproto
@ -245,8 +245,10 @@ func NewEchoServiceHTTPClient(client *http.Client) EchoServiceHTTPClient {
func (c *EchoServiceHTTPClientImpl) Echo(ctx context.Context, in *SimpleMessage, opts ...http.CallOption) (*SimpleMessage, error) {
var out SimpleMessage
path := binding.EncodeURL("/v1/example/echo/{id}", in, false)
pattern := "/v1/example/echo/{id}"
path := binding.EncodeURL(pattern, in, false)
opts = append(opts, http.Operation("/testproto.EchoService/Echo"))
opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "POST", path, nil, &out, opts...)
if err != nil {
return nil, err
@ -256,8 +258,10 @@ func (c *EchoServiceHTTPClientImpl) Echo(ctx context.Context, in *SimpleMessage,
func (c *EchoServiceHTTPClientImpl) EchoBody(ctx context.Context, in *SimpleMessage, opts ...http.CallOption) (*SimpleMessage, error) {
var out SimpleMessage
path := binding.EncodeURL("/v1/example/echo_body", in, false)
pattern := "/v1/example/echo_body"
path := binding.EncodeURL(pattern, in, false)
opts = append(opts, http.Operation("/testproto.EchoService/EchoBody"))
opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "POST", path, in, &out, opts...)
if err != nil {
return nil, err
@ -267,8 +271,10 @@ func (c *EchoServiceHTTPClientImpl) EchoBody(ctx context.Context, in *SimpleMess
func (c *EchoServiceHTTPClientImpl) EchoDelete(ctx context.Context, in *SimpleMessage, opts ...http.CallOption) (*SimpleMessage, error) {
var out SimpleMessage
path := binding.EncodeURL("/v1/example/echo_delete/{id}/{num}", in, false)
pattern := "/v1/example/echo_delete/{id}/{num}"
path := binding.EncodeURL(pattern, in, false)
opts = append(opts, http.Operation("/testproto.EchoService/EchoDelete"))
opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "DELETE", path, nil, &out, opts...)
if err != nil {
return nil, err
@ -278,8 +284,10 @@ func (c *EchoServiceHTTPClientImpl) EchoDelete(ctx context.Context, in *SimpleMe
func (c *EchoServiceHTTPClientImpl) EchoPatch(ctx context.Context, in *DynamicMessageUpdate, opts ...http.CallOption) (*DynamicMessageUpdate, error) {
var out DynamicMessageUpdate
path := binding.EncodeURL("/v1/example/echo_patch", in, false)
pattern := "/v1/example/echo_patch"
path := binding.EncodeURL(pattern, in, false)
opts = append(opts, http.Operation("/testproto.EchoService/EchoPatch"))
opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "PATCH", path, in.Body, &out, opts...)
if err != nil {
return nil, err
@ -289,8 +297,10 @@ func (c *EchoServiceHTTPClientImpl) EchoPatch(ctx context.Context, in *DynamicMe
func (c *EchoServiceHTTPClientImpl) EchoResponseBody(ctx context.Context, in *DynamicMessageUpdate, opts ...http.CallOption) (*DynamicMessageUpdate, error) {
var out DynamicMessageUpdate
path := binding.EncodeURL("/v1/example/echo_response_body", in, false)
pattern := "/v1/example/echo_response_body"
path := binding.EncodeURL(pattern, in, false)
opts = append(opts, http.Operation("/testproto.EchoService/EchoResponseBody"))
opts = append(opts, http.PathTemplate(pattern))
err := c.cc.Invoke(ctx, "POST", path, in, &out.Body, opts...)
if err != nil {
return nil, err

@ -19,16 +19,16 @@ import (
)
// EncodeURL encode proto message to url path.
func EncodeURL(pathPattern string, msg proto.Message, needQuery bool) string {
func EncodeURL(pathTemplate string, msg proto.Message, needQuery bool) string {
if msg == nil || (reflect.ValueOf(msg).Kind() == reflect.Ptr && reflect.ValueOf(msg).IsNil()) {
return pathPattern
return pathTemplate
}
reg := regexp.MustCompile(`/{[.\w]+}`)
if reg == nil {
return pathPattern
return pathTemplate
}
pathParams := make(map[string]struct{}, 0)
path := reg.ReplaceAllStringFunc(pathPattern, func(in string) string {
path := reg.ReplaceAllStringFunc(pathTemplate, func(in string) string {
if len(in) < 4 {
return in
}

@ -13,8 +13,9 @@ type CallOption interface {
}
type callInfo struct {
contentType string
operation string
contentType string
operation string
pathTemplate string
}
// EmptyCallOption does not alter the Call configuration.
@ -45,8 +46,9 @@ func (o ContentTypeCallOption) before(c *callInfo) error {
func defaultCallInfo(path string) callInfo {
return callInfo{
contentType: "application/json",
operation: path,
contentType: "application/json",
operation: path,
pathTemplate: path,
}
}
@ -65,3 +67,19 @@ func (o OperationCallOption) before(c *callInfo) error {
c.operation = o.Operation
return nil
}
// PathTemplate is http path template
func PathTemplate(pattern string) CallOption {
return PathTemplateCallOption{Pattern: pattern}
}
// PathTemplateCallOption is set path template for client call
type PathTemplateCallOption struct {
EmptyCallOption
Pattern string
}
func (o PathTemplateCallOption) before(c *callInfo) error {
c.pathTemplate = o.Pattern
return nil
}

@ -197,10 +197,11 @@ func (client *Client) Invoke(ctx context.Context, method, path string, args inte
req.Header.Set("User-Agent", client.opts.userAgent)
}
ctx = transport.NewClientContext(ctx, &Transport{
endpoint: client.opts.endpoint,
header: headerCarrier(req.Header),
operation: c.operation,
request: req,
endpoint: client.opts.endpoint,
header: headerCarrier(req.Header),
operation: c.operation,
request: req,
pathTemplate: c.pathTemplate,
})
return client.invoke(ctx, req, args, reply, c)
}

@ -162,11 +162,17 @@ func (s *Server) filter() mux.MiddlewareFunc {
ctx, cancel = context.WithTimeout(ctx, s.timeout)
defer cancel()
}
pathTemplate := req.URL.Path
if route := mux.CurrentRoute(req); route != nil {
// /path/123 -> /path/{id}
pathTemplate, _ = route.GetPathTemplate()
}
tr := &Transport{
endpoint: s.endpoint.String(),
operation: req.RequestURI,
header: headerCarrier(req.Header),
request: req,
endpoint: s.endpoint.String(),
operation: pathTemplate,
header: headerCarrier(req.Header),
request: req,
pathTemplate: pathTemplate,
}
if r := mux.CurrentRoute(req); r != nil {
if path, err := r.GetPathTemplate(); err == nil {

@ -13,10 +13,11 @@ var (
// Transport is an HTTP transport.
type Transport struct {
endpoint string
operation string
header headerCarrier
request *http.Request
endpoint string
operation string
header headerCarrier
request *http.Request
pathTemplate string
}
// Kind returns the transport kind.
@ -44,6 +45,11 @@ func (tr *Transport) Request() *http.Request {
return tr.request
}
// PathTemplate returns the http path template.
func (tr *Transport) PathTemplate() string {
return tr.pathTemplate
}
// SetOperation sets the transport operation.
func SetOperation(ctx context.Context, op string) {
if tr, ok := transport.FromServerContext(ctx); ok {

Loading…
Cancel
Save