Moved to google.golang.org/genproto/googleapis/api/annotations
Fixes #52
This commit is contained in:
2
vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/gengateway/doc.go
generated
vendored
Normal file
2
vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/gengateway/doc.go
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package gengateway provides a code generator for grpc gateway files.
|
||||
package gengateway
|
111
vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/gengateway/generator.go
generated
vendored
Normal file
111
vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/gengateway/generator.go
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
package gengateway
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/golang/protobuf/proto"
|
||||
plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/descriptor"
|
||||
gen "github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/generator"
|
||||
options "google.golang.org/genproto/googleapis/api/annotations"
|
||||
)
|
||||
|
||||
var (
|
||||
errNoTargetService = errors.New("no target service defined in the file")
|
||||
)
|
||||
|
||||
type generator struct {
|
||||
reg *descriptor.Registry
|
||||
baseImports []descriptor.GoPackage
|
||||
useRequestContext bool
|
||||
}
|
||||
|
||||
// New returns a new generator which generates grpc gateway files.
|
||||
func New(reg *descriptor.Registry, useRequestContext bool) gen.Generator {
|
||||
var imports []descriptor.GoPackage
|
||||
for _, pkgpath := range []string{
|
||||
"io",
|
||||
"net/http",
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime",
|
||||
"github.com/grpc-ecosystem/grpc-gateway/utilities",
|
||||
"github.com/golang/protobuf/proto",
|
||||
"golang.org/x/net/context",
|
||||
"google.golang.org/grpc",
|
||||
"google.golang.org/grpc/codes",
|
||||
"google.golang.org/grpc/grpclog",
|
||||
} {
|
||||
pkg := descriptor.GoPackage{
|
||||
Path: pkgpath,
|
||||
Name: path.Base(pkgpath),
|
||||
}
|
||||
if err := reg.ReserveGoPackageAlias(pkg.Name, pkg.Path); err != nil {
|
||||
for i := 0; ; i++ {
|
||||
alias := fmt.Sprintf("%s_%d", pkg.Name, i)
|
||||
if err := reg.ReserveGoPackageAlias(alias, pkg.Path); err != nil {
|
||||
continue
|
||||
}
|
||||
pkg.Alias = alias
|
||||
break
|
||||
}
|
||||
}
|
||||
imports = append(imports, pkg)
|
||||
}
|
||||
return &generator{reg: reg, baseImports: imports, useRequestContext: useRequestContext}
|
||||
}
|
||||
|
||||
func (g *generator) Generate(targets []*descriptor.File) ([]*plugin.CodeGeneratorResponse_File, error) {
|
||||
var files []*plugin.CodeGeneratorResponse_File
|
||||
for _, file := range targets {
|
||||
glog.V(1).Infof("Processing %s", file.GetName())
|
||||
code, err := g.generate(file)
|
||||
if err == errNoTargetService {
|
||||
glog.V(1).Infof("%s: %v", file.GetName(), err)
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
formatted, err := format.Source([]byte(code))
|
||||
if err != nil {
|
||||
glog.Errorf("%v: %s", err, code)
|
||||
return nil, err
|
||||
}
|
||||
name := file.GetName()
|
||||
ext := filepath.Ext(name)
|
||||
base := strings.TrimSuffix(name, ext)
|
||||
output := fmt.Sprintf("%s.pb.gw.go", base)
|
||||
files = append(files, &plugin.CodeGeneratorResponse_File{
|
||||
Name: proto.String(output),
|
||||
Content: proto.String(string(formatted)),
|
||||
})
|
||||
glog.V(1).Infof("Will emit %s", output)
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func (g *generator) generate(file *descriptor.File) (string, error) {
|
||||
pkgSeen := make(map[string]bool)
|
||||
var imports []descriptor.GoPackage
|
||||
for _, pkg := range g.baseImports {
|
||||
pkgSeen[pkg.Path] = true
|
||||
imports = append(imports, pkg)
|
||||
}
|
||||
for _, svc := range file.Services {
|
||||
for _, m := range svc.Methods {
|
||||
pkg := m.RequestType.File.GoPkg
|
||||
if m.Options == nil || !proto.HasExtension(m.Options, options.E_Http) ||
|
||||
pkg == file.GoPkg || pkgSeen[pkg.Path] {
|
||||
continue
|
||||
}
|
||||
pkgSeen[pkg.Path] = true
|
||||
imports = append(imports, pkg)
|
||||
}
|
||||
}
|
||||
return applyTemplate(param{File: file, Imports: imports, UseRequestContext: g.useRequestContext})
|
||||
}
|
88
vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/gengateway/generator_test.go
generated
vendored
Normal file
88
vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/gengateway/generator_test.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
package gengateway
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
protodescriptor "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/descriptor"
|
||||
)
|
||||
|
||||
func TestGenerateServiceWithoutBindings(t *testing.T) {
|
||||
msgdesc := &protodescriptor.DescriptorProto{
|
||||
Name: proto.String("ExampleMessage"),
|
||||
}
|
||||
msg := &descriptor.Message{
|
||||
DescriptorProto: msgdesc,
|
||||
}
|
||||
msg1 := &descriptor.Message{
|
||||
DescriptorProto: msgdesc,
|
||||
File: &descriptor.File{
|
||||
GoPkg: descriptor.GoPackage{
|
||||
Path: "github.com/golang/protobuf/ptypes/empty",
|
||||
Name: "empty",
|
||||
},
|
||||
},
|
||||
}
|
||||
meth := &protodescriptor.MethodDescriptorProto{
|
||||
Name: proto.String("Example"),
|
||||
InputType: proto.String("ExampleMessage"),
|
||||
OutputType: proto.String("ExampleMessage"),
|
||||
}
|
||||
meth1 := &protodescriptor.MethodDescriptorProto{
|
||||
Name: proto.String("ExampleWithoutBindings"),
|
||||
InputType: proto.String("empty.Empty"),
|
||||
OutputType: proto.String("empty.Empty"),
|
||||
}
|
||||
svc := &protodescriptor.ServiceDescriptorProto{
|
||||
Name: proto.String("ExampleService"),
|
||||
Method: []*protodescriptor.MethodDescriptorProto{meth, meth1},
|
||||
}
|
||||
file := descriptor.File{
|
||||
FileDescriptorProto: &protodescriptor.FileDescriptorProto{
|
||||
Name: proto.String("example.proto"),
|
||||
Package: proto.String("example"),
|
||||
Dependency: []string{"a.example/b/c.proto", "a.example/d/e.proto"},
|
||||
MessageType: []*protodescriptor.DescriptorProto{msgdesc},
|
||||
Service: []*protodescriptor.ServiceDescriptorProto{svc},
|
||||
},
|
||||
GoPkg: descriptor.GoPackage{
|
||||
Path: "example.com/path/to/example/example.pb",
|
||||
Name: "example_pb",
|
||||
},
|
||||
Messages: []*descriptor.Message{msg},
|
||||
Services: []*descriptor.Service{
|
||||
{
|
||||
ServiceDescriptorProto: svc,
|
||||
Methods: []*descriptor.Method{
|
||||
{
|
||||
MethodDescriptorProto: meth,
|
||||
RequestType: msg,
|
||||
ResponseType: msg,
|
||||
Bindings: []*descriptor.Binding{
|
||||
{
|
||||
HTTPMethod: "GET",
|
||||
Body: &descriptor.Body{FieldPath: nil},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
MethodDescriptorProto: meth1,
|
||||
RequestType: msg1,
|
||||
ResponseType: msg1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
g := &generator{}
|
||||
got, err := g.generate(crossLinkFixture(&file))
|
||||
if err != nil {
|
||||
t.Errorf("generate(%#v) failed with %v; want success", file, err)
|
||||
return
|
||||
}
|
||||
if notwanted := `"github.com/golang/protobuf/ptypes/empty"`; strings.Contains(got, notwanted) {
|
||||
t.Errorf("generate(%#v) = %s; does not want to contain %s", file, got, notwanted)
|
||||
}
|
||||
}
|
398
vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/gengateway/template.go
generated
vendored
Normal file
398
vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/gengateway/template.go
generated
vendored
Normal file
@@ -0,0 +1,398 @@
|
||||
package gengateway
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/descriptor"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/utilities"
|
||||
)
|
||||
|
||||
type param struct {
|
||||
*descriptor.File
|
||||
Imports []descriptor.GoPackage
|
||||
UseRequestContext bool
|
||||
}
|
||||
|
||||
type binding struct {
|
||||
*descriptor.Binding
|
||||
}
|
||||
|
||||
// HasQueryParam determines if the binding needs parameters in query string.
|
||||
//
|
||||
// It sometimes returns true even though actually the binding does not need.
|
||||
// But it is not serious because it just results in a small amount of extra codes generated.
|
||||
func (b binding) HasQueryParam() bool {
|
||||
if b.Body != nil && len(b.Body.FieldPath) == 0 {
|
||||
return false
|
||||
}
|
||||
fields := make(map[string]bool)
|
||||
for _, f := range b.Method.RequestType.Fields {
|
||||
fields[f.GetName()] = true
|
||||
}
|
||||
if b.Body != nil {
|
||||
delete(fields, b.Body.FieldPath.String())
|
||||
}
|
||||
for _, p := range b.PathParams {
|
||||
delete(fields, p.FieldPath.String())
|
||||
}
|
||||
return len(fields) > 0
|
||||
}
|
||||
|
||||
func (b binding) QueryParamFilter() queryParamFilter {
|
||||
var seqs [][]string
|
||||
if b.Body != nil {
|
||||
seqs = append(seqs, strings.Split(b.Body.FieldPath.String(), "."))
|
||||
}
|
||||
for _, p := range b.PathParams {
|
||||
seqs = append(seqs, strings.Split(p.FieldPath.String(), "."))
|
||||
}
|
||||
return queryParamFilter{utilities.NewDoubleArray(seqs)}
|
||||
}
|
||||
|
||||
// queryParamFilter is a wrapper of utilities.DoubleArray which provides String() to output DoubleArray.Encoding in a stable and predictable format.
|
||||
type queryParamFilter struct {
|
||||
*utilities.DoubleArray
|
||||
}
|
||||
|
||||
func (f queryParamFilter) String() string {
|
||||
encodings := make([]string, len(f.Encoding))
|
||||
for str, enc := range f.Encoding {
|
||||
encodings[enc] = fmt.Sprintf("%q: %d", str, enc)
|
||||
}
|
||||
e := strings.Join(encodings, ", ")
|
||||
return fmt.Sprintf("&utilities.DoubleArray{Encoding: map[string]int{%s}, Base: %#v, Check: %#v}", e, f.Base, f.Check)
|
||||
}
|
||||
|
||||
type trailerParams struct {
|
||||
Services []*descriptor.Service
|
||||
UseRequestContext bool
|
||||
}
|
||||
|
||||
func applyTemplate(p param) (string, error) {
|
||||
w := bytes.NewBuffer(nil)
|
||||
if err := headerTemplate.Execute(w, p); err != nil {
|
||||
return "", err
|
||||
}
|
||||
var targetServices []*descriptor.Service
|
||||
for _, svc := range p.Services {
|
||||
var methodWithBindingsSeen bool
|
||||
for _, meth := range svc.Methods {
|
||||
glog.V(2).Infof("Processing %s.%s", svc.GetName(), meth.GetName())
|
||||
methName := strings.Title(*meth.Name)
|
||||
meth.Name = &methName
|
||||
for _, b := range meth.Bindings {
|
||||
methodWithBindingsSeen = true
|
||||
if err := handlerTemplate.Execute(w, binding{Binding: b}); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
}
|
||||
if methodWithBindingsSeen {
|
||||
targetServices = append(targetServices, svc)
|
||||
}
|
||||
}
|
||||
if len(targetServices) == 0 {
|
||||
return "", errNoTargetService
|
||||
}
|
||||
|
||||
tp := trailerParams{
|
||||
Services: targetServices,
|
||||
UseRequestContext: p.UseRequestContext,
|
||||
}
|
||||
if err := trailerTemplate.Execute(w, tp); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return w.String(), nil
|
||||
}
|
||||
|
||||
var (
|
||||
headerTemplate = template.Must(template.New("header").Parse(`
|
||||
// Code generated by protoc-gen-grpc-gateway
|
||||
// source: {{.GetName}}
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package {{.GoPkg.Name}} is a reverse proxy.
|
||||
|
||||
It translates gRPC into RESTful JSON APIs.
|
||||
*/
|
||||
package {{.GoPkg.Name}}
|
||||
import (
|
||||
{{range $i := .Imports}}{{if $i.Standard}}{{$i | printf "%s\n"}}{{end}}{{end}}
|
||||
|
||||
{{range $i := .Imports}}{{if not $i.Standard}}{{$i | printf "%s\n"}}{{end}}{{end}}
|
||||
)
|
||||
|
||||
var _ codes.Code
|
||||
var _ io.Reader
|
||||
var _ = runtime.String
|
||||
var _ = utilities.NewDoubleArray
|
||||
`))
|
||||
|
||||
handlerTemplate = template.Must(template.New("handler").Parse(`
|
||||
{{if and .Method.GetClientStreaming .Method.GetServerStreaming}}
|
||||
{{template "bidi-streaming-request-func" .}}
|
||||
{{else if .Method.GetClientStreaming}}
|
||||
{{template "client-streaming-request-func" .}}
|
||||
{{else}}
|
||||
{{template "client-rpc-request-func" .}}
|
||||
{{end}}
|
||||
`))
|
||||
|
||||
_ = template.Must(handlerTemplate.New("request-func-signature").Parse(strings.Replace(`
|
||||
{{if .Method.GetServerStreaming}}
|
||||
func request_{{.Method.Service.GetName}}_{{.Method.GetName}}_{{.Index}}(ctx context.Context, marshaler runtime.Marshaler, client {{.Method.Service.GetName}}Client, req *http.Request, pathParams map[string]string) ({{.Method.Service.GetName}}_{{.Method.GetName}}Client, runtime.ServerMetadata, error)
|
||||
{{else}}
|
||||
func request_{{.Method.Service.GetName}}_{{.Method.GetName}}_{{.Index}}(ctx context.Context, marshaler runtime.Marshaler, client {{.Method.Service.GetName}}Client, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error)
|
||||
{{end}}`, "\n", "", -1)))
|
||||
|
||||
_ = template.Must(handlerTemplate.New("client-streaming-request-func").Parse(`
|
||||
{{template "request-func-signature" .}} {
|
||||
var metadata runtime.ServerMetadata
|
||||
stream, err := client.{{.Method.GetName}}(ctx)
|
||||
if err != nil {
|
||||
grpclog.Printf("Failed to start streaming: %v", err)
|
||||
return nil, metadata, err
|
||||
}
|
||||
dec := marshaler.NewDecoder(req.Body)
|
||||
for {
|
||||
var protoReq {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}}
|
||||
err = dec.Decode(&protoReq)
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
grpclog.Printf("Failed to decode request: %v", err)
|
||||
return nil, metadata, grpc.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
if err = stream.Send(&protoReq); err != nil {
|
||||
grpclog.Printf("Failed to send request: %v", err)
|
||||
return nil, metadata, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := stream.CloseSend(); err != nil {
|
||||
grpclog.Printf("Failed to terminate client stream: %v", err)
|
||||
return nil, metadata, err
|
||||
}
|
||||
header, err := stream.Header()
|
||||
if err != nil {
|
||||
grpclog.Printf("Failed to get header from client: %v", err)
|
||||
return nil, metadata, err
|
||||
}
|
||||
metadata.HeaderMD = header
|
||||
{{if .Method.GetServerStreaming}}
|
||||
return stream, metadata, nil
|
||||
{{else}}
|
||||
msg, err := stream.CloseAndRecv()
|
||||
metadata.TrailerMD = stream.Trailer()
|
||||
return msg, metadata, err
|
||||
{{end}}
|
||||
}
|
||||
`))
|
||||
|
||||
_ = template.Must(handlerTemplate.New("client-rpc-request-func").Parse(`
|
||||
{{if .HasQueryParam}}
|
||||
var (
|
||||
filter_{{.Method.Service.GetName}}_{{.Method.GetName}}_{{.Index}} = {{.QueryParamFilter}}
|
||||
)
|
||||
{{end}}
|
||||
{{template "request-func-signature" .}} {
|
||||
var protoReq {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}}
|
||||
var metadata runtime.ServerMetadata
|
||||
{{if .Body}}
|
||||
if err := marshaler.NewDecoder(req.Body).Decode(&{{.Body.RHS "protoReq"}}); err != nil {
|
||||
return nil, metadata, grpc.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
{{end}}
|
||||
{{if .PathParams}}
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
{{range $param := .PathParams}}
|
||||
val, ok = pathParams[{{$param | printf "%q"}}]
|
||||
if !ok {
|
||||
return nil, metadata, grpc.Errorf(codes.InvalidArgument, "missing parameter %s", {{$param | printf "%q"}})
|
||||
}
|
||||
{{if $param.IsNestedProto3 }}
|
||||
err = runtime.PopulateFieldFromPath(&protoReq, {{$param | printf "%q"}}, val)
|
||||
{{else}}
|
||||
{{$param.RHS "protoReq"}}, err = {{$param.ConvertFuncExpr}}(val)
|
||||
{{end}}
|
||||
if err != nil {
|
||||
return nil, metadata, err
|
||||
}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if .HasQueryParam}}
|
||||
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_{{.Method.Service.GetName}}_{{.Method.GetName}}_{{.Index}}); err != nil {
|
||||
return nil, metadata, grpc.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
{{end}}
|
||||
{{if .Method.GetServerStreaming}}
|
||||
stream, err := client.{{.Method.GetName}}(ctx, &protoReq)
|
||||
if err != nil {
|
||||
return nil, metadata, err
|
||||
}
|
||||
header, err := stream.Header()
|
||||
if err != nil {
|
||||
return nil, metadata, err
|
||||
}
|
||||
metadata.HeaderMD = header
|
||||
return stream, metadata, nil
|
||||
{{else}}
|
||||
msg, err := client.{{.Method.GetName}}(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
{{end}}
|
||||
}`))
|
||||
|
||||
_ = template.Must(handlerTemplate.New("bidi-streaming-request-func").Parse(`
|
||||
{{template "request-func-signature" .}} {
|
||||
var metadata runtime.ServerMetadata
|
||||
stream, err := client.{{.Method.GetName}}(ctx)
|
||||
if err != nil {
|
||||
grpclog.Printf("Failed to start streaming: %v", err)
|
||||
return nil, metadata, err
|
||||
}
|
||||
dec := marshaler.NewDecoder(req.Body)
|
||||
handleSend := func() error {
|
||||
var protoReq {{.Method.RequestType.GoType .Method.Service.File.GoPkg.Path}}
|
||||
err = dec.Decode(&protoReq)
|
||||
if err == io.EOF {
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
grpclog.Printf("Failed to decode request: %v", err)
|
||||
return err
|
||||
}
|
||||
if err = stream.Send(&protoReq); err != nil {
|
||||
grpclog.Printf("Failed to send request: %v", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err := handleSend(); err != nil {
|
||||
if cerr := stream.CloseSend(); cerr != nil {
|
||||
grpclog.Printf("Failed to terminate client stream: %v", cerr)
|
||||
}
|
||||
if err == io.EOF {
|
||||
return stream, metadata, nil
|
||||
}
|
||||
return nil, metadata, err
|
||||
}
|
||||
go func() {
|
||||
for {
|
||||
if err := handleSend(); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err := stream.CloseSend(); err != nil {
|
||||
grpclog.Printf("Failed to terminate client stream: %v", err)
|
||||
}
|
||||
}()
|
||||
header, err := stream.Header()
|
||||
if err != nil {
|
||||
grpclog.Printf("Failed to get header from client: %v", err)
|
||||
return nil, metadata, err
|
||||
}
|
||||
metadata.HeaderMD = header
|
||||
return stream, metadata, nil
|
||||
}
|
||||
`))
|
||||
|
||||
trailerTemplate = template.Must(template.New("trailer").Parse(`
|
||||
{{$UseRequestContext := .UseRequestContext}}
|
||||
{{range $svc := .Services}}
|
||||
// Register{{$svc.GetName}}HandlerFromEndpoint is same as Register{{$svc.GetName}}Handler but
|
||||
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
|
||||
func Register{{$svc.GetName}}HandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
|
||||
conn, err := grpc.Dial(endpoint, opts...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
<-ctx.Done()
|
||||
if cerr := conn.Close(); cerr != nil {
|
||||
grpclog.Printf("Failed to close conn to %s: %v", endpoint, cerr)
|
||||
}
|
||||
}()
|
||||
}()
|
||||
|
||||
return Register{{$svc.GetName}}Handler(ctx, mux, conn)
|
||||
}
|
||||
|
||||
// Register{{$svc.GetName}}Handler registers the http handlers for service {{$svc.GetName}} to "mux".
|
||||
// The handlers forward requests to the grpc endpoint over "conn".
|
||||
func Register{{$svc.GetName}}Handler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
|
||||
client := New{{$svc.GetName}}Client(conn)
|
||||
{{range $m := $svc.Methods}}
|
||||
{{range $b := $m.Bindings}}
|
||||
mux.Handle({{$b.HTTPMethod | printf "%q"}}, pattern_{{$svc.GetName}}_{{$m.GetName}}_{{$b.Index}}, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
{{- if $UseRequestContext }}
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
{{- else -}}
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
{{- end }}
|
||||
defer cancel()
|
||||
if cn, ok := w.(http.CloseNotifier); ok {
|
||||
go func(done <-chan struct{}, closed <-chan bool) {
|
||||
select {
|
||||
case <-done:
|
||||
case <-closed:
|
||||
cancel()
|
||||
}
|
||||
}(ctx.Done(), cn.CloseNotify())
|
||||
}
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, outboundMarshaler, w, req, err)
|
||||
}
|
||||
resp, md, err := request_{{$svc.GetName}}_{{$m.GetName}}_{{$b.Index}}(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
{{if $m.GetServerStreaming}}
|
||||
forward_{{$svc.GetName}}_{{$m.GetName}}_{{$b.Index}}(ctx, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...)
|
||||
{{else}}
|
||||
forward_{{$svc.GetName}}_{{$m.GetName}}_{{$b.Index}}(ctx, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
{{end}}
|
||||
})
|
||||
{{end}}
|
||||
{{end}}
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
{{range $m := $svc.Methods}}
|
||||
{{range $b := $m.Bindings}}
|
||||
pattern_{{$svc.GetName}}_{{$m.GetName}}_{{$b.Index}} = runtime.MustPattern(runtime.NewPattern({{$b.PathTmpl.Version}}, {{$b.PathTmpl.OpCodes | printf "%#v"}}, {{$b.PathTmpl.Pool | printf "%#v"}}, {{$b.PathTmpl.Verb | printf "%q"}}))
|
||||
{{end}}
|
||||
{{end}}
|
||||
)
|
||||
|
||||
var (
|
||||
{{range $m := $svc.Methods}}
|
||||
{{range $b := $m.Bindings}}
|
||||
forward_{{$svc.GetName}}_{{$m.GetName}}_{{$b.Index}} = {{if $m.GetServerStreaming}}runtime.ForwardResponseStream{{else}}runtime.ForwardResponseMessage{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
)
|
||||
{{end}}`))
|
||||
)
|
404
vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/gengateway/template_test.go
generated
vendored
Normal file
404
vendor/github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/gengateway/template_test.go
generated
vendored
Normal file
@@ -0,0 +1,404 @@
|
||||
package gengateway
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
protodescriptor "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/descriptor"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/httprule"
|
||||
)
|
||||
|
||||
func crossLinkFixture(f *descriptor.File) *descriptor.File {
|
||||
for _, m := range f.Messages {
|
||||
m.File = f
|
||||
}
|
||||
for _, svc := range f.Services {
|
||||
svc.File = f
|
||||
for _, m := range svc.Methods {
|
||||
m.Service = svc
|
||||
for _, b := range m.Bindings {
|
||||
b.Method = m
|
||||
for _, param := range b.PathParams {
|
||||
param.Method = m
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func TestApplyTemplateHeader(t *testing.T) {
|
||||
msgdesc := &protodescriptor.DescriptorProto{
|
||||
Name: proto.String("ExampleMessage"),
|
||||
}
|
||||
meth := &protodescriptor.MethodDescriptorProto{
|
||||
Name: proto.String("Example"),
|
||||
InputType: proto.String("ExampleMessage"),
|
||||
OutputType: proto.String("ExampleMessage"),
|
||||
}
|
||||
svc := &protodescriptor.ServiceDescriptorProto{
|
||||
Name: proto.String("ExampleService"),
|
||||
Method: []*protodescriptor.MethodDescriptorProto{meth},
|
||||
}
|
||||
msg := &descriptor.Message{
|
||||
DescriptorProto: msgdesc,
|
||||
}
|
||||
file := descriptor.File{
|
||||
FileDescriptorProto: &protodescriptor.FileDescriptorProto{
|
||||
Name: proto.String("example.proto"),
|
||||
Package: proto.String("example"),
|
||||
Dependency: []string{"a.example/b/c.proto", "a.example/d/e.proto"},
|
||||
MessageType: []*protodescriptor.DescriptorProto{msgdesc},
|
||||
Service: []*protodescriptor.ServiceDescriptorProto{svc},
|
||||
},
|
||||
GoPkg: descriptor.GoPackage{
|
||||
Path: "example.com/path/to/example/example.pb",
|
||||
Name: "example_pb",
|
||||
},
|
||||
Messages: []*descriptor.Message{msg},
|
||||
Services: []*descriptor.Service{
|
||||
{
|
||||
ServiceDescriptorProto: svc,
|
||||
Methods: []*descriptor.Method{
|
||||
{
|
||||
MethodDescriptorProto: meth,
|
||||
RequestType: msg,
|
||||
ResponseType: msg,
|
||||
Bindings: []*descriptor.Binding{
|
||||
{
|
||||
HTTPMethod: "GET",
|
||||
Body: &descriptor.Body{FieldPath: nil},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
got, err := applyTemplate(param{File: crossLinkFixture(&file)})
|
||||
if err != nil {
|
||||
t.Errorf("applyTemplate(%#v) failed with %v; want success", file, err)
|
||||
return
|
||||
}
|
||||
if want := "package example_pb\n"; !strings.Contains(got, want) {
|
||||
t.Errorf("applyTemplate(%#v) = %s; want to contain %s", file, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyTemplateRequestWithoutClientStreaming(t *testing.T) {
|
||||
msgdesc := &protodescriptor.DescriptorProto{
|
||||
Name: proto.String("ExampleMessage"),
|
||||
Field: []*protodescriptor.FieldDescriptorProto{
|
||||
{
|
||||
Name: proto.String("nested"),
|
||||
Label: protodescriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
|
||||
Type: protodescriptor.FieldDescriptorProto_TYPE_MESSAGE.Enum(),
|
||||
TypeName: proto.String("NestedMessage"),
|
||||
Number: proto.Int32(1),
|
||||
},
|
||||
},
|
||||
}
|
||||
nesteddesc := &protodescriptor.DescriptorProto{
|
||||
Name: proto.String("NestedMessage"),
|
||||
Field: []*protodescriptor.FieldDescriptorProto{
|
||||
{
|
||||
Name: proto.String("int32"),
|
||||
Label: protodescriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
|
||||
Type: protodescriptor.FieldDescriptorProto_TYPE_INT32.Enum(),
|
||||
Number: proto.Int32(1),
|
||||
},
|
||||
{
|
||||
Name: proto.String("bool"),
|
||||
Label: protodescriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
|
||||
Type: protodescriptor.FieldDescriptorProto_TYPE_BOOL.Enum(),
|
||||
Number: proto.Int32(2),
|
||||
},
|
||||
},
|
||||
}
|
||||
meth := &protodescriptor.MethodDescriptorProto{
|
||||
Name: proto.String("Echo"),
|
||||
InputType: proto.String("ExampleMessage"),
|
||||
OutputType: proto.String("ExampleMessage"),
|
||||
ClientStreaming: proto.Bool(false),
|
||||
}
|
||||
svc := &protodescriptor.ServiceDescriptorProto{
|
||||
Name: proto.String("ExampleService"),
|
||||
Method: []*protodescriptor.MethodDescriptorProto{meth},
|
||||
}
|
||||
for _, spec := range []struct {
|
||||
serverStreaming bool
|
||||
sigWant string
|
||||
}{
|
||||
{
|
||||
serverStreaming: false,
|
||||
sigWant: `func request_ExampleService_Echo_0(ctx context.Context, marshaler runtime.Marshaler, client ExampleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {`,
|
||||
},
|
||||
{
|
||||
serverStreaming: true,
|
||||
sigWant: `func request_ExampleService_Echo_0(ctx context.Context, marshaler runtime.Marshaler, client ExampleServiceClient, req *http.Request, pathParams map[string]string) (ExampleService_EchoClient, runtime.ServerMetadata, error) {`,
|
||||
},
|
||||
} {
|
||||
meth.ServerStreaming = proto.Bool(spec.serverStreaming)
|
||||
|
||||
msg := &descriptor.Message{
|
||||
DescriptorProto: msgdesc,
|
||||
}
|
||||
nested := &descriptor.Message{
|
||||
DescriptorProto: nesteddesc,
|
||||
}
|
||||
|
||||
nestedField := &descriptor.Field{
|
||||
Message: msg,
|
||||
FieldDescriptorProto: msg.GetField()[0],
|
||||
}
|
||||
intField := &descriptor.Field{
|
||||
Message: nested,
|
||||
FieldDescriptorProto: nested.GetField()[0],
|
||||
}
|
||||
boolField := &descriptor.Field{
|
||||
Message: nested,
|
||||
FieldDescriptorProto: nested.GetField()[1],
|
||||
}
|
||||
file := descriptor.File{
|
||||
FileDescriptorProto: &protodescriptor.FileDescriptorProto{
|
||||
Name: proto.String("example.proto"),
|
||||
Package: proto.String("example"),
|
||||
MessageType: []*protodescriptor.DescriptorProto{msgdesc, nesteddesc},
|
||||
Service: []*protodescriptor.ServiceDescriptorProto{svc},
|
||||
},
|
||||
GoPkg: descriptor.GoPackage{
|
||||
Path: "example.com/path/to/example/example.pb",
|
||||
Name: "example_pb",
|
||||
},
|
||||
Messages: []*descriptor.Message{msg, nested},
|
||||
Services: []*descriptor.Service{
|
||||
{
|
||||
ServiceDescriptorProto: svc,
|
||||
Methods: []*descriptor.Method{
|
||||
{
|
||||
MethodDescriptorProto: meth,
|
||||
RequestType: msg,
|
||||
ResponseType: msg,
|
||||
Bindings: []*descriptor.Binding{
|
||||
{
|
||||
HTTPMethod: "POST",
|
||||
PathTmpl: httprule.Template{
|
||||
Version: 1,
|
||||
OpCodes: []int{0, 0},
|
||||
},
|
||||
PathParams: []descriptor.Parameter{
|
||||
{
|
||||
FieldPath: descriptor.FieldPath([]descriptor.FieldPathComponent{
|
||||
{
|
||||
Name: "nested",
|
||||
Target: nestedField,
|
||||
},
|
||||
{
|
||||
Name: "int32",
|
||||
Target: intField,
|
||||
},
|
||||
}),
|
||||
Target: intField,
|
||||
},
|
||||
},
|
||||
Body: &descriptor.Body{
|
||||
FieldPath: descriptor.FieldPath([]descriptor.FieldPathComponent{
|
||||
{
|
||||
Name: "nested",
|
||||
Target: nestedField,
|
||||
},
|
||||
{
|
||||
Name: "bool",
|
||||
Target: boolField,
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
got, err := applyTemplate(param{File: crossLinkFixture(&file)})
|
||||
if err != nil {
|
||||
t.Errorf("applyTemplate(%#v) failed with %v; want success", file, err)
|
||||
return
|
||||
}
|
||||
if want := spec.sigWant; !strings.Contains(got, want) {
|
||||
t.Errorf("applyTemplate(%#v) = %s; want to contain %s", file, got, want)
|
||||
}
|
||||
if want := `marshaler.NewDecoder(req.Body).Decode(&protoReq.GetNested().Bool)`; !strings.Contains(got, want) {
|
||||
t.Errorf("applyTemplate(%#v) = %s; want to contain %s", file, got, want)
|
||||
}
|
||||
if want := `val, ok = pathParams["nested.int32"]`; !strings.Contains(got, want) {
|
||||
t.Errorf("applyTemplate(%#v) = %s; want to contain %s", file, got, want)
|
||||
}
|
||||
if want := `protoReq.GetNested().Int32, err = runtime.Int32P(val)`; !strings.Contains(got, want) {
|
||||
t.Errorf("applyTemplate(%#v) = %s; want to contain %s", file, got, want)
|
||||
}
|
||||
if want := `func RegisterExampleServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {`; !strings.Contains(got, want) {
|
||||
t.Errorf("applyTemplate(%#v) = %s; want to contain %s", file, got, want)
|
||||
}
|
||||
if want := `pattern_ExampleService_Echo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{0, 0}, []string(nil), ""))`; !strings.Contains(got, want) {
|
||||
t.Errorf("applyTemplate(%#v) = %s; want to contain %s", file, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyTemplateRequestWithClientStreaming(t *testing.T) {
|
||||
msgdesc := &protodescriptor.DescriptorProto{
|
||||
Name: proto.String("ExampleMessage"),
|
||||
Field: []*protodescriptor.FieldDescriptorProto{
|
||||
{
|
||||
Name: proto.String("nested"),
|
||||
Label: protodescriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
|
||||
Type: protodescriptor.FieldDescriptorProto_TYPE_MESSAGE.Enum(),
|
||||
TypeName: proto.String("NestedMessage"),
|
||||
Number: proto.Int32(1),
|
||||
},
|
||||
},
|
||||
}
|
||||
nesteddesc := &protodescriptor.DescriptorProto{
|
||||
Name: proto.String("NestedMessage"),
|
||||
Field: []*protodescriptor.FieldDescriptorProto{
|
||||
{
|
||||
Name: proto.String("int32"),
|
||||
Label: protodescriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
|
||||
Type: protodescriptor.FieldDescriptorProto_TYPE_INT32.Enum(),
|
||||
Number: proto.Int32(1),
|
||||
},
|
||||
{
|
||||
Name: proto.String("bool"),
|
||||
Label: protodescriptor.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
|
||||
Type: protodescriptor.FieldDescriptorProto_TYPE_BOOL.Enum(),
|
||||
Number: proto.Int32(2),
|
||||
},
|
||||
},
|
||||
}
|
||||
meth := &protodescriptor.MethodDescriptorProto{
|
||||
Name: proto.String("Echo"),
|
||||
InputType: proto.String("ExampleMessage"),
|
||||
OutputType: proto.String("ExampleMessage"),
|
||||
ClientStreaming: proto.Bool(true),
|
||||
}
|
||||
svc := &protodescriptor.ServiceDescriptorProto{
|
||||
Name: proto.String("ExampleService"),
|
||||
Method: []*protodescriptor.MethodDescriptorProto{meth},
|
||||
}
|
||||
for _, spec := range []struct {
|
||||
serverStreaming bool
|
||||
sigWant string
|
||||
}{
|
||||
{
|
||||
serverStreaming: false,
|
||||
sigWant: `func request_ExampleService_Echo_0(ctx context.Context, marshaler runtime.Marshaler, client ExampleServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {`,
|
||||
},
|
||||
{
|
||||
serverStreaming: true,
|
||||
sigWant: `func request_ExampleService_Echo_0(ctx context.Context, marshaler runtime.Marshaler, client ExampleServiceClient, req *http.Request, pathParams map[string]string) (ExampleService_EchoClient, runtime.ServerMetadata, error) {`,
|
||||
},
|
||||
} {
|
||||
meth.ServerStreaming = proto.Bool(spec.serverStreaming)
|
||||
|
||||
msg := &descriptor.Message{
|
||||
DescriptorProto: msgdesc,
|
||||
}
|
||||
nested := &descriptor.Message{
|
||||
DescriptorProto: nesteddesc,
|
||||
}
|
||||
|
||||
nestedField := &descriptor.Field{
|
||||
Message: msg,
|
||||
FieldDescriptorProto: msg.GetField()[0],
|
||||
}
|
||||
intField := &descriptor.Field{
|
||||
Message: nested,
|
||||
FieldDescriptorProto: nested.GetField()[0],
|
||||
}
|
||||
boolField := &descriptor.Field{
|
||||
Message: nested,
|
||||
FieldDescriptorProto: nested.GetField()[1],
|
||||
}
|
||||
file := descriptor.File{
|
||||
FileDescriptorProto: &protodescriptor.FileDescriptorProto{
|
||||
Name: proto.String("example.proto"),
|
||||
Package: proto.String("example"),
|
||||
MessageType: []*protodescriptor.DescriptorProto{msgdesc, nesteddesc},
|
||||
Service: []*protodescriptor.ServiceDescriptorProto{svc},
|
||||
},
|
||||
GoPkg: descriptor.GoPackage{
|
||||
Path: "example.com/path/to/example/example.pb",
|
||||
Name: "example_pb",
|
||||
},
|
||||
Messages: []*descriptor.Message{msg, nested},
|
||||
Services: []*descriptor.Service{
|
||||
{
|
||||
ServiceDescriptorProto: svc,
|
||||
Methods: []*descriptor.Method{
|
||||
{
|
||||
MethodDescriptorProto: meth,
|
||||
RequestType: msg,
|
||||
ResponseType: msg,
|
||||
Bindings: []*descriptor.Binding{
|
||||
{
|
||||
HTTPMethod: "POST",
|
||||
PathTmpl: httprule.Template{
|
||||
Version: 1,
|
||||
OpCodes: []int{0, 0},
|
||||
},
|
||||
PathParams: []descriptor.Parameter{
|
||||
{
|
||||
FieldPath: descriptor.FieldPath([]descriptor.FieldPathComponent{
|
||||
{
|
||||
Name: "nested",
|
||||
Target: nestedField,
|
||||
},
|
||||
{
|
||||
Name: "int32",
|
||||
Target: intField,
|
||||
},
|
||||
}),
|
||||
Target: intField,
|
||||
},
|
||||
},
|
||||
Body: &descriptor.Body{
|
||||
FieldPath: descriptor.FieldPath([]descriptor.FieldPathComponent{
|
||||
{
|
||||
Name: "nested",
|
||||
Target: nestedField,
|
||||
},
|
||||
{
|
||||
Name: "bool",
|
||||
Target: boolField,
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
got, err := applyTemplate(param{File: crossLinkFixture(&file)})
|
||||
if err != nil {
|
||||
t.Errorf("applyTemplate(%#v) failed with %v; want success", file, err)
|
||||
return
|
||||
}
|
||||
if want := spec.sigWant; !strings.Contains(got, want) {
|
||||
t.Errorf("applyTemplate(%#v) = %s; want to contain %s", file, got, want)
|
||||
}
|
||||
if want := `marshaler.NewDecoder(req.Body)`; !strings.Contains(got, want) {
|
||||
t.Errorf("applyTemplate(%#v) = %s; want to contain %s", file, got, want)
|
||||
}
|
||||
if want := `func RegisterExampleServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {`; !strings.Contains(got, want) {
|
||||
t.Errorf("applyTemplate(%#v) = %s; want to contain %s", file, got, want)
|
||||
}
|
||||
if want := `pattern_ExampleService_Echo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{0, 0}, []string(nil), ""))`; !strings.Contains(got, want) {
|
||||
t.Errorf("applyTemplate(%#v) = %s; want to contain %s", file, got, want)
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user