transport/http: add vars to http context (#1037)

* add vars to http context

* add query to http context

* remove http deps

* clean request decoder
pull/1040/head
Tony Chen 4 years ago committed by GitHub
parent 00088f644a
commit eca0f35cb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      api/metadata/metadata_http.pb.go
  2. 6
      cmd/protoc-gen-go-http/http.go
  3. 2
      cmd/protoc-gen-go-http/template.go
  4. 10
      examples/blog/api/blog/v1/blog_http.pb.go
  5. 6
      examples/helloworld/helloworld/helloworld_http.pb.go
  6. 3
      examples/http/middlewares/handlers.go
  7. 6
      examples/traces/api/message/message_http.pb.go
  8. 6
      examples/traces/api/user/user_http.pb.go
  9. 16
      internal/testproto/echo_service_http.pb.go
  10. 17
      transport/http/binding/bind.go
  11. 7
      transport/http/codec.go
  12. 11
      transport/http/context.go

@ -6,7 +6,6 @@ package metadata
import ( import (
context "context" context "context"
middleware "github.com/go-kratos/kratos/v2/middleware"
transport "github.com/go-kratos/kratos/v2/transport" transport "github.com/go-kratos/kratos/v2/transport"
http "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" binding "github.com/go-kratos/kratos/v2/transport/http/binding"
@ -15,9 +14,8 @@ import (
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the kratos package it is being compiled against. // is compatible with the kratos package it is being compiled against.
var _ = new(context.Context) var _ = new(context.Context)
var _ = new(middleware.Middleware)
var _ = new(transport.Transporter) var _ = new(transport.Transporter)
var _ = binding.BindVars var _ = binding.EncodeVars
const _ = http.SupportPackageIsVersion1 const _ = http.SupportPackageIsVersion1
@ -57,7 +55,7 @@ func _Metadata_GetServiceDesc0_HTTP_Handler(srv MetadataHTTPServer) func(ctx htt
if err := ctx.Bind(&in); err != nil { if err := ctx.Bind(&in); err != nil {
return err return err
} }
if err := binding.BindVars(ctx.Vars(), &in); err != nil { if err := ctx.BindVars(&in); err != nil {
return err return err
} }
transport.SetOperation(ctx, "/kratos.api.Metadata/GetServiceDesc") transport.SetOperation(ctx, "/kratos.api.Metadata/GetServiceDesc")

@ -12,10 +12,9 @@ import (
const ( const (
contextPackage = protogen.GoImportPath("context") contextPackage = protogen.GoImportPath("context")
middlewarePackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/middleware") transportPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/transport")
transportHTTPPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/transport/http") transportHTTPPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/transport/http")
bindingPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/transport/http/binding") bindingPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/transport/http/binding")
transportPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/transport")
) )
var methodSets = make(map[string]int) var methodSets = make(map[string]int)
@ -45,9 +44,8 @@ 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("// 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("// is compatible with the kratos package it is being compiled against.")
g.P("var _ = new(", contextPackage.Ident("Context"), ")") g.P("var _ = new(", contextPackage.Ident("Context"), ")")
g.P("var _ = new(", middlewarePackage.Ident("Middleware"), ")")
g.P("var _ = new(", transportPackage.Ident("Transporter"), ")") g.P("var _ = new(", transportPackage.Ident("Transporter"), ")")
g.P("var _ = ", bindingPackage.Ident("BindVars")) g.P("var _ = ", bindingPackage.Ident("EncodeVars"))
g.P("const _ = ", transportHTTPPackage.Ident("SupportPackageIsVersion1")) g.P("const _ = ", transportHTTPPackage.Ident("SupportPackageIsVersion1"))
g.P() g.P()

@ -30,7 +30,7 @@ func _{{$svrType}}_{{.Name}}{{.Num}}_HTTP_Handler(srv {{$svrType}}HTTPServer) fu
return err return err
} }
{{- if ne (len .Vars) 0}} {{- if ne (len .Vars) 0}}
if err := binding.BindVars(ctx.Vars(), &in); err != nil { if err := ctx.BindVars(&in); err != nil {
return err return err
} }
{{- end}} {{- end}}

@ -6,7 +6,6 @@ package v1
import ( import (
context "context" context "context"
middleware "github.com/go-kratos/kratos/v2/middleware"
transport "github.com/go-kratos/kratos/v2/transport" transport "github.com/go-kratos/kratos/v2/transport"
http "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" binding "github.com/go-kratos/kratos/v2/transport/http/binding"
@ -15,9 +14,8 @@ import (
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the kratos package it is being compiled against. // is compatible with the kratos package it is being compiled against.
var _ = new(context.Context) var _ = new(context.Context)
var _ = new(middleware.Middleware)
var _ = new(transport.Transporter) var _ = new(transport.Transporter)
var _ = binding.BindVars var _ = binding.EncodeVars
const _ = http.SupportPackageIsVersion1 const _ = http.SupportPackageIsVersion1
@ -63,7 +61,7 @@ func _BlogService_UpdateArticle0_HTTP_Handler(srv BlogServiceHTTPServer) func(ct
if err := ctx.Bind(&in); err != nil { if err := ctx.Bind(&in); err != nil {
return err return err
} }
if err := binding.BindVars(ctx.Vars(), &in); err != nil { if err := ctx.BindVars(&in); err != nil {
return err return err
} }
transport.SetOperation(ctx, "/blog.api.v1.BlogService/UpdateArticle") transport.SetOperation(ctx, "/blog.api.v1.BlogService/UpdateArticle")
@ -85,7 +83,7 @@ func _BlogService_DeleteArticle0_HTTP_Handler(srv BlogServiceHTTPServer) func(ct
if err := ctx.Bind(&in); err != nil { if err := ctx.Bind(&in); err != nil {
return err return err
} }
if err := binding.BindVars(ctx.Vars(), &in); err != nil { if err := ctx.BindVars(&in); err != nil {
return err return err
} }
transport.SetOperation(ctx, "/blog.api.v1.BlogService/DeleteArticle") transport.SetOperation(ctx, "/blog.api.v1.BlogService/DeleteArticle")
@ -107,7 +105,7 @@ func _BlogService_GetArticle0_HTTP_Handler(srv BlogServiceHTTPServer) func(ctx h
if err := ctx.Bind(&in); err != nil { if err := ctx.Bind(&in); err != nil {
return err return err
} }
if err := binding.BindVars(ctx.Vars(), &in); err != nil { if err := ctx.BindVars(&in); err != nil {
return err return err
} }
transport.SetOperation(ctx, "/blog.api.v1.BlogService/GetArticle") transport.SetOperation(ctx, "/blog.api.v1.BlogService/GetArticle")

@ -6,7 +6,6 @@ package helloworld
import ( import (
context "context" context "context"
middleware "github.com/go-kratos/kratos/v2/middleware"
transport "github.com/go-kratos/kratos/v2/transport" transport "github.com/go-kratos/kratos/v2/transport"
http "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" binding "github.com/go-kratos/kratos/v2/transport/http/binding"
@ -15,9 +14,8 @@ import (
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the kratos package it is being compiled against. // is compatible with the kratos package it is being compiled against.
var _ = new(context.Context) var _ = new(context.Context)
var _ = new(middleware.Middleware)
var _ = new(transport.Transporter) var _ = new(transport.Transporter)
var _ = binding.BindVars var _ = binding.EncodeVars
const _ = http.SupportPackageIsVersion1 const _ = http.SupportPackageIsVersion1
@ -36,7 +34,7 @@ func _Greeter_SayHello0_HTTP_Handler(srv GreeterHTTPServer) func(ctx http.Contex
if err := ctx.Bind(&in); err != nil { if err := ctx.Bind(&in); err != nil {
return err return err
} }
if err := binding.BindVars(ctx.Vars(), &in); err != nil { if err := ctx.BindVars(&in); err != nil {
return err return err
} }
transport.SetOperation(ctx, "/helloworld.Greeter/SayHello") transport.SetOperation(ctx, "/helloworld.Greeter/SayHello")

@ -6,7 +6,6 @@ import (
"github.com/go-kratos/kratos/examples/helloworld/helloworld" "github.com/go-kratos/kratos/examples/helloworld/helloworld"
"github.com/go-kratos/kratos/v2/transport" "github.com/go-kratos/kratos/v2/transport"
"github.com/go-kratos/kratos/v2/transport/http" "github.com/go-kratos/kratos/v2/transport/http"
"github.com/go-kratos/kratos/v2/transport/http/binding"
) )
func sayHelloHandler(ctx http.Context) error { func sayHelloHandler(ctx http.Context) error {
@ -16,7 +15,7 @@ func sayHelloHandler(ctx http.Context) error {
} }
// binding /hello/{name} to in.Name // binding /hello/{name} to in.Name
if err := binding.BindVars(ctx.Vars(), &in); err != nil { if err := ctx.BindVars(&in); err != nil {
return err return err
} }

@ -6,7 +6,6 @@ package v1
import ( import (
context "context" context "context"
middleware "github.com/go-kratos/kratos/v2/middleware"
transport "github.com/go-kratos/kratos/v2/transport" transport "github.com/go-kratos/kratos/v2/transport"
http "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" binding "github.com/go-kratos/kratos/v2/transport/http/binding"
@ -15,9 +14,8 @@ import (
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the kratos package it is being compiled against. // is compatible with the kratos package it is being compiled against.
var _ = new(context.Context) var _ = new(context.Context)
var _ = new(middleware.Middleware)
var _ = new(transport.Transporter) var _ = new(transport.Transporter)
var _ = binding.BindVars var _ = binding.EncodeVars
const _ = http.SupportPackageIsVersion1 const _ = http.SupportPackageIsVersion1
@ -36,7 +34,7 @@ func _MessageService_GetUserMessage0_HTTP_Handler(srv MessageServiceHTTPServer)
if err := ctx.Bind(&in); err != nil { if err := ctx.Bind(&in); err != nil {
return err return err
} }
if err := binding.BindVars(ctx.Vars(), &in); err != nil { if err := ctx.BindVars(&in); err != nil {
return err return err
} }
transport.SetOperation(ctx, "/api.message.v1.MessageService/GetUserMessage") transport.SetOperation(ctx, "/api.message.v1.MessageService/GetUserMessage")

@ -6,7 +6,6 @@ package v1
import ( import (
context "context" context "context"
middleware "github.com/go-kratos/kratos/v2/middleware"
transport "github.com/go-kratos/kratos/v2/transport" transport "github.com/go-kratos/kratos/v2/transport"
http "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" binding "github.com/go-kratos/kratos/v2/transport/http/binding"
@ -15,9 +14,8 @@ import (
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the kratos package it is being compiled against. // is compatible with the kratos package it is being compiled against.
var _ = new(context.Context) var _ = new(context.Context)
var _ = new(middleware.Middleware)
var _ = new(transport.Transporter) var _ = new(transport.Transporter)
var _ = binding.BindVars var _ = binding.EncodeVars
const _ = http.SupportPackageIsVersion1 const _ = http.SupportPackageIsVersion1
@ -36,7 +34,7 @@ func _User_GetMyMessages0_HTTP_Handler(srv UserHTTPServer) func(ctx http.Context
if err := ctx.Bind(&in); err != nil { if err := ctx.Bind(&in); err != nil {
return err return err
} }
if err := binding.BindVars(ctx.Vars(), &in); err != nil { if err := ctx.BindVars(&in); err != nil {
return err return err
} }
transport.SetOperation(ctx, "/api.user.v1.User/GetMyMessages") transport.SetOperation(ctx, "/api.user.v1.User/GetMyMessages")

@ -6,7 +6,6 @@ package testproto
import ( import (
context "context" context "context"
middleware "github.com/go-kratos/kratos/v2/middleware"
transport "github.com/go-kratos/kratos/v2/transport" transport "github.com/go-kratos/kratos/v2/transport"
http "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" binding "github.com/go-kratos/kratos/v2/transport/http/binding"
@ -15,9 +14,8 @@ import (
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the kratos package it is being compiled against. // is compatible with the kratos package it is being compiled against.
var _ = new(context.Context) var _ = new(context.Context)
var _ = new(middleware.Middleware)
var _ = new(transport.Transporter) var _ = new(transport.Transporter)
var _ = binding.BindVars var _ = binding.EncodeVars
const _ = http.SupportPackageIsVersion1 const _ = http.SupportPackageIsVersion1
@ -48,7 +46,7 @@ func _EchoService_Echo0_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Co
if err := ctx.Bind(&in); err != nil { if err := ctx.Bind(&in); err != nil {
return err return err
} }
if err := binding.BindVars(ctx.Vars(), &in); err != nil { if err := ctx.BindVars(&in); err != nil {
return err return err
} }
transport.SetOperation(ctx, "/testproto.EchoService/Echo") transport.SetOperation(ctx, "/testproto.EchoService/Echo")
@ -70,7 +68,7 @@ func _EchoService_Echo1_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Co
if err := ctx.Bind(&in); err != nil { if err := ctx.Bind(&in); err != nil {
return err return err
} }
if err := binding.BindVars(ctx.Vars(), &in); err != nil { if err := ctx.BindVars(&in); err != nil {
return err return err
} }
transport.SetOperation(ctx, "/testproto.EchoService/Echo") transport.SetOperation(ctx, "/testproto.EchoService/Echo")
@ -92,7 +90,7 @@ func _EchoService_Echo2_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Co
if err := ctx.Bind(&in); err != nil { if err := ctx.Bind(&in); err != nil {
return err return err
} }
if err := binding.BindVars(ctx.Vars(), &in); err != nil { if err := ctx.BindVars(&in); err != nil {
return err return err
} }
transport.SetOperation(ctx, "/testproto.EchoService/Echo") transport.SetOperation(ctx, "/testproto.EchoService/Echo")
@ -114,7 +112,7 @@ func _EchoService_Echo3_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Co
if err := ctx.Bind(&in); err != nil { if err := ctx.Bind(&in); err != nil {
return err return err
} }
if err := binding.BindVars(ctx.Vars(), &in); err != nil { if err := ctx.BindVars(&in); err != nil {
return err return err
} }
transport.SetOperation(ctx, "/testproto.EchoService/Echo") transport.SetOperation(ctx, "/testproto.EchoService/Echo")
@ -136,7 +134,7 @@ func _EchoService_Echo4_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx http.Co
if err := ctx.Bind(&in); err != nil { if err := ctx.Bind(&in); err != nil {
return err return err
} }
if err := binding.BindVars(ctx.Vars(), &in); err != nil { if err := ctx.BindVars(&in); err != nil {
return err return err
} }
transport.SetOperation(ctx, "/testproto.EchoService/Echo") transport.SetOperation(ctx, "/testproto.EchoService/Echo")
@ -196,7 +194,7 @@ func _EchoService_EchoDelete0_HTTP_Handler(srv EchoServiceHTTPServer) func(ctx h
if err := ctx.Bind(&in); err != nil { if err := ctx.Bind(&in); err != nil {
return err return err
} }
if err := binding.BindVars(ctx.Vars(), &in); err != nil { if err := ctx.BindVars(&in); err != nil {
return err return err
} }
transport.SetOperation(ctx, "/testproto.EchoService/EchoDelete") transport.SetOperation(ctx, "/testproto.EchoService/EchoDelete")

@ -2,10 +2,19 @@ package binding
import ( import (
"net/http" "net/http"
"net/url"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
// BindQuery bind vars parameters to target.
func BindQuery(vars url.Values, target interface{}) error {
if msg, ok := target.(proto.Message); ok {
return mapProto(msg, vars)
}
return mapForm(target, vars)
}
// BindForm bind form parameters to target. // BindForm bind form parameters to target.
func BindForm(req *http.Request, target interface{}) error { func BindForm(req *http.Request, target interface{}) error {
if err := req.ParseForm(); err != nil { if err := req.ParseForm(); err != nil {
@ -16,11 +25,3 @@ func BindForm(req *http.Request, target interface{}) error {
} }
return mapForm(target, req.Form) return mapForm(target, req.Form)
} }
// BindVars bind map parameters to target.
func BindVars(values map[string][]string, target interface{}) error {
if msg, ok := target.(proto.Message); ok {
return mapProto(msg, values)
}
return mapForm(target, values)
}

@ -24,8 +24,7 @@ type EncodeErrorFunc func(http.ResponseWriter, *http.Request, error)
// DefaultRequestDecoder decodes the request body to object. // DefaultRequestDecoder decodes the request body to object.
func DefaultRequestDecoder(r *http.Request, v interface{}) error { func DefaultRequestDecoder(r *http.Request, v interface{}) error {
codec, ok := CodecForRequest(r, "Content-Type") if codec, ok := CodecForRequest(r, "Content-Type"); ok {
if ok {
data, err := ioutil.ReadAll(r.Body) data, err := ioutil.ReadAll(r.Body)
if err != nil { if err != nil {
return errors.BadRequest("CODEC", err.Error()) return errors.BadRequest("CODEC", err.Error())
@ -33,11 +32,11 @@ func DefaultRequestDecoder(r *http.Request, v interface{}) error {
if err := codec.Unmarshal(data, v); err != nil { if err := codec.Unmarshal(data, v); err != nil {
return errors.BadRequest("CODEC", err.Error()) return errors.BadRequest("CODEC", err.Error())
} }
} else { return nil
}
if err := binding.BindForm(r, v); err != nil { if err := binding.BindForm(r, v); err != nil {
return errors.BadRequest("CODEC", err.Error()) return errors.BadRequest("CODEC", err.Error())
} }
}
return nil return nil
} }

@ -10,6 +10,7 @@ import (
"time" "time"
"github.com/go-kratos/kratos/v2/middleware" "github.com/go-kratos/kratos/v2/middleware"
"github.com/go-kratos/kratos/v2/transport/http/binding"
"github.com/gorilla/mux" "github.com/gorilla/mux"
) )
@ -22,12 +23,16 @@ type HandlerFunc func(Context) error
type Context interface { type Context interface {
context.Context context.Context
Vars() url.Values Vars() url.Values
Query() url.Values
Form() url.Values Form() url.Values
Header() http.Header Header() http.Header
Request() *http.Request Request() *http.Request
Response() http.ResponseWriter Response() http.ResponseWriter
Middleware(middleware.Handler) middleware.Handler Middleware(middleware.Handler) middleware.Handler
Bind(interface{}) error Bind(interface{}) error
BindVars(interface{}) error
BindQuery(interface{}) error
BindForm(interface{}) error
Returns(interface{}, error) error Returns(interface{}, error) error
Result(int, interface{}) error Result(int, interface{}) error
JSON(int, interface{}) error JSON(int, interface{}) error
@ -62,12 +67,18 @@ func (c *wrapper) Form() url.Values {
} }
return c.req.Form return c.req.Form
} }
func (c *wrapper) Query() url.Values {
return c.req.URL.Query()
}
func (c *wrapper) Request() *http.Request { return c.req } func (c *wrapper) Request() *http.Request { return c.req }
func (c *wrapper) Response() http.ResponseWriter { return c.res } func (c *wrapper) Response() http.ResponseWriter { return c.res }
func (c *wrapper) Middleware(h middleware.Handler) middleware.Handler { func (c *wrapper) Middleware(h middleware.Handler) middleware.Handler {
return middleware.Chain(c.route.srv.ms...)(h) 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) Bind(v interface{}) error { return c.route.srv.dec(c.req, v) }
func (c *wrapper) BindVars(v interface{}) error { return binding.BindQuery(c.Vars(), v) }
func (c *wrapper) BindQuery(v interface{}) error { return binding.BindQuery(c.Query(), v) }
func (c *wrapper) BindForm(v interface{}) error { return binding.BindForm(c.req, v) }
func (c *wrapper) Returns(v interface{}, err error) error { func (c *wrapper) Returns(v interface{}, err error) error {
if err != nil { if err != nil {
return err return err

Loading…
Cancel
Save