mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-19 09:52:49 +00:00
Version bump to grpc-gateway v1.3.0
This commit is contained in:
parent
0abafb2404
commit
132278ec6e
12
Godeps/Godeps.json
generated
12
Godeps/Godeps.json
generated
@ -1871,18 +1871,18 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/grpc-ecosystem/grpc-gateway/runtime",
|
"ImportPath": "github.com/grpc-ecosystem/grpc-gateway/runtime",
|
||||||
"Comment": "v1.1.0-25-g84398b9",
|
"Comment": "v1.3.0",
|
||||||
"Rev": "84398b94e188ee336f307779b57b3aa91af7063c"
|
"Rev": "8cc3a55af3bcf171a1c23a90c4df9cf591706104"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/grpc-ecosystem/grpc-gateway/runtime/internal",
|
"ImportPath": "github.com/grpc-ecosystem/grpc-gateway/runtime/internal",
|
||||||
"Comment": "v1.1.0-25-g84398b9",
|
"Comment": "v1.3.0",
|
||||||
"Rev": "84398b94e188ee336f307779b57b3aa91af7063c"
|
"Rev": "8cc3a55af3bcf171a1c23a90c4df9cf591706104"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/grpc-ecosystem/grpc-gateway/utilities",
|
"ImportPath": "github.com/grpc-ecosystem/grpc-gateway/utilities",
|
||||||
"Comment": "v1.1.0-25-g84398b9",
|
"Comment": "v1.3.0",
|
||||||
"Rev": "84398b94e188ee336f307779b57b3aa91af7063c"
|
"Rev": "8cc3a55af3bcf171a1c23a90c4df9cf591706104"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/hashicorp/golang-lru",
|
"ImportPath": "github.com/hashicorp/golang-lru",
|
||||||
|
3
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/BUILD
generated
vendored
3
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/BUILD
generated
vendored
@ -15,6 +15,7 @@ go_library(
|
|||||||
"mux.go",
|
"mux.go",
|
||||||
"pattern.go",
|
"pattern.go",
|
||||||
"proto2_convert.go",
|
"proto2_convert.go",
|
||||||
|
"proto_errors.go",
|
||||||
"query.go",
|
"query.go",
|
||||||
],
|
],
|
||||||
importpath = "github.com/grpc-ecosystem/grpc-gateway/runtime",
|
importpath = "github.com/grpc-ecosystem/grpc-gateway/runtime",
|
||||||
@ -25,10 +26,10 @@ go_library(
|
|||||||
"//vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/internal:go_default_library",
|
"//vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/internal:go_default_library",
|
||||||
"//vendor/github.com/grpc-ecosystem/grpc-gateway/utilities:go_default_library",
|
"//vendor/github.com/grpc-ecosystem/grpc-gateway/utilities:go_default_library",
|
||||||
"//vendor/golang.org/x/net/context:go_default_library",
|
"//vendor/golang.org/x/net/context:go_default_library",
|
||||||
"//vendor/google.golang.org/grpc:go_default_library",
|
|
||||||
"//vendor/google.golang.org/grpc/codes:go_default_library",
|
"//vendor/google.golang.org/grpc/codes:go_default_library",
|
||||||
"//vendor/google.golang.org/grpc/grpclog:go_default_library",
|
"//vendor/google.golang.org/grpc/grpclog:go_default_library",
|
||||||
"//vendor/google.golang.org/grpc/metadata:go_default_library",
|
"//vendor/google.golang.org/grpc/metadata:go_default_library",
|
||||||
|
"//vendor/google.golang.org/grpc/status:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
64
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/context.go
generated
vendored
64
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/context.go
generated
vendored
@ -9,18 +9,23 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/grpclog"
|
"google.golang.org/grpc/grpclog"
|
||||||
"google.golang.org/grpc/metadata"
|
"google.golang.org/grpc/metadata"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MetadataHeaderPrefix is prepended to HTTP headers in order to convert them to
|
// MetadataHeaderPrefix is the http prefix that represents custom metadata
|
||||||
// gRPC metadata for incoming requests processed by grpc-gateway
|
// parameters to or from a gRPC call.
|
||||||
const MetadataHeaderPrefix = "Grpc-Metadata-"
|
const MetadataHeaderPrefix = "Grpc-Metadata-"
|
||||||
|
|
||||||
|
// MetadataPrefix is the prefix for grpc-gateway supplied custom metadata fields.
|
||||||
|
const MetadataPrefix = "grpcgateway-"
|
||||||
|
|
||||||
// MetadataTrailerPrefix is prepended to gRPC metadata as it is converted to
|
// MetadataTrailerPrefix is prepended to gRPC metadata as it is converted to
|
||||||
// HTTP headers in a response handled by grpc-gateway
|
// HTTP headers in a response handled by grpc-gateway
|
||||||
const MetadataTrailerPrefix = "Grpc-Trailer-"
|
const MetadataTrailerPrefix = "Grpc-Trailer-"
|
||||||
|
|
||||||
const metadataGrpcTimeout = "Grpc-Timeout"
|
const metadataGrpcTimeout = "Grpc-Timeout"
|
||||||
|
|
||||||
const xForwardedFor = "X-Forwarded-For"
|
const xForwardedFor = "X-Forwarded-For"
|
||||||
@ -39,25 +44,25 @@ At a minimum, the RemoteAddr is included in the fashion of "X-Forwarded-For",
|
|||||||
except that the forwarded destination is not another HTTP service but rather
|
except that the forwarded destination is not another HTTP service but rather
|
||||||
a gRPC service.
|
a gRPC service.
|
||||||
*/
|
*/
|
||||||
func AnnotateContext(ctx context.Context, req *http.Request) (context.Context, error) {
|
func AnnotateContext(ctx context.Context, mux *ServeMux, req *http.Request) (context.Context, error) {
|
||||||
var pairs []string
|
var pairs []string
|
||||||
timeout := DefaultContextTimeout
|
timeout := DefaultContextTimeout
|
||||||
if tm := req.Header.Get(metadataGrpcTimeout); tm != "" {
|
if tm := req.Header.Get(metadataGrpcTimeout); tm != "" {
|
||||||
var err error
|
var err error
|
||||||
timeout, err = timeoutDecode(tm)
|
timeout, err = timeoutDecode(tm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, grpc.Errorf(codes.InvalidArgument, "invalid grpc-timeout: %s", tm)
|
return nil, status.Errorf(codes.InvalidArgument, "invalid grpc-timeout: %s", tm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for key, vals := range req.Header {
|
for key, vals := range req.Header {
|
||||||
for _, val := range vals {
|
for _, val := range vals {
|
||||||
if key == "Authorization" {
|
// For backwards-compatibility, pass through 'authorization' header with no prefix.
|
||||||
|
if strings.ToLower(key) == "authorization" {
|
||||||
pairs = append(pairs, "authorization", val)
|
pairs = append(pairs, "authorization", val)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(key, MetadataHeaderPrefix) {
|
if h, ok := mux.incomingHeaderMatcher(key); ok {
|
||||||
pairs = append(pairs, key[len(MetadataHeaderPrefix):], val)
|
pairs = append(pairs, h, val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,7 +90,11 @@ func AnnotateContext(ctx context.Context, req *http.Request) (context.Context, e
|
|||||||
if len(pairs) == 0 {
|
if len(pairs) == 0 {
|
||||||
return ctx, nil
|
return ctx, nil
|
||||||
}
|
}
|
||||||
return metadata.NewContext(ctx, metadata.Pairs(pairs...)), nil
|
md := metadata.Pairs(pairs...)
|
||||||
|
if mux.metadataAnnotator != nil {
|
||||||
|
md = metadata.Join(md, mux.metadataAnnotator(ctx, req))
|
||||||
|
}
|
||||||
|
return metadata.NewOutgoingContext(ctx, md), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServerMetadata consists of metadata sent from gRPC server.
|
// ServerMetadata consists of metadata sent from gRPC server.
|
||||||
@ -141,3 +150,38 @@ func timeoutUnitToDuration(u uint8) (d time.Duration, ok bool) {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isPermanentHTTPHeader checks whether hdr belongs to the list of
|
||||||
|
// permenant request headers maintained by IANA.
|
||||||
|
// http://www.iana.org/assignments/message-headers/message-headers.xml
|
||||||
|
func isPermanentHTTPHeader(hdr string) bool {
|
||||||
|
switch hdr {
|
||||||
|
case
|
||||||
|
"Accept",
|
||||||
|
"Accept-Charset",
|
||||||
|
"Accept-Language",
|
||||||
|
"Accept-Ranges",
|
||||||
|
"Authorization",
|
||||||
|
"Cache-Control",
|
||||||
|
"Content-Type",
|
||||||
|
"Cookie",
|
||||||
|
"Date",
|
||||||
|
"Expect",
|
||||||
|
"From",
|
||||||
|
"Host",
|
||||||
|
"If-Match",
|
||||||
|
"If-Modified-Since",
|
||||||
|
"If-None-Match",
|
||||||
|
"If-Schedule-Tag-Match",
|
||||||
|
"If-Unmodified-Since",
|
||||||
|
"Max-Forwards",
|
||||||
|
"Origin",
|
||||||
|
"Pragma",
|
||||||
|
"Referer",
|
||||||
|
"User-Agent",
|
||||||
|
"Via",
|
||||||
|
"Warning":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
20
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/errors.go
generated
vendored
20
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/errors.go
generated
vendored
@ -6,9 +6,9 @@ import (
|
|||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/grpclog"
|
"google.golang.org/grpc/grpclog"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HTTPStatusFromCode converts a gRPC error code into the corresponding HTTP response status.
|
// HTTPStatusFromCode converts a gRPC error code into the corresponding HTTP response status.
|
||||||
@ -64,7 +64,7 @@ var (
|
|||||||
|
|
||||||
type errorBody struct {
|
type errorBody struct {
|
||||||
Error string `protobuf:"bytes,1,name=error" json:"error"`
|
Error string `protobuf:"bytes,1,name=error" json:"error"`
|
||||||
Code int `protobuf:"bytes,2,name=code" json:"code"`
|
Code int32 `protobuf:"varint,2,name=code" json:"code"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//Make this also conform to proto.Message for builtin JSONPb Marshaler
|
//Make this also conform to proto.Message for builtin JSONPb Marshaler
|
||||||
@ -78,14 +78,20 @@ func (*errorBody) ProtoMessage() {}
|
|||||||
//
|
//
|
||||||
// The response body returned by this function is a JSON object,
|
// The response body returned by this function is a JSON object,
|
||||||
// which contains a member whose key is "error" and whose value is err.Error().
|
// which contains a member whose key is "error" and whose value is err.Error().
|
||||||
func DefaultHTTPError(ctx context.Context, marshaler Marshaler, w http.ResponseWriter, _ *http.Request, err error) {
|
func DefaultHTTPError(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, _ *http.Request, err error) {
|
||||||
const fallback = `{"error": "failed to marshal error message"}`
|
const fallback = `{"error": "failed to marshal error message"}`
|
||||||
|
|
||||||
w.Header().Del("Trailer")
|
w.Header().Del("Trailer")
|
||||||
w.Header().Set("Content-Type", marshaler.ContentType())
|
w.Header().Set("Content-Type", marshaler.ContentType())
|
||||||
|
|
||||||
|
s, ok := status.FromError(err)
|
||||||
|
if !ok {
|
||||||
|
s = status.New(codes.Unknown, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
body := &errorBody{
|
body := &errorBody{
|
||||||
Error: grpc.ErrorDesc(err),
|
Error: s.Message(),
|
||||||
Code: int(grpc.Code(err)),
|
Code: int32(s.Code()),
|
||||||
}
|
}
|
||||||
|
|
||||||
buf, merr := marshaler.Marshal(body)
|
buf, merr := marshaler.Marshal(body)
|
||||||
@ -103,9 +109,9 @@ func DefaultHTTPError(ctx context.Context, marshaler Marshaler, w http.ResponseW
|
|||||||
grpclog.Printf("Failed to extract ServerMetadata from context")
|
grpclog.Printf("Failed to extract ServerMetadata from context")
|
||||||
}
|
}
|
||||||
|
|
||||||
handleForwardResponseServerMetadata(w, md)
|
handleForwardResponseServerMetadata(w, mux, md)
|
||||||
handleForwardResponseTrailerHeader(w, md)
|
handleForwardResponseTrailerHeader(w, md)
|
||||||
st := HTTPStatusFromCode(grpc.Code(err))
|
st := HTTPStatusFromCode(s.Code())
|
||||||
w.WriteHeader(st)
|
w.WriteHeader(st)
|
||||||
if _, err := w.Write(buf); err != nil {
|
if _, err := w.Write(buf); err != nil {
|
||||||
grpclog.Printf("Failed to write response: %v", err)
|
grpclog.Printf("Failed to write response: %v", err)
|
||||||
|
35
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/handler.go
generated
vendored
35
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/handler.go
generated
vendored
@ -9,12 +9,13 @@ import (
|
|||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/grpc-ecosystem/grpc-gateway/runtime/internal"
|
"github.com/grpc-ecosystem/grpc-gateway/runtime/internal"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/grpclog"
|
"google.golang.org/grpc/grpclog"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ForwardResponseStream forwards the stream from gRPC server to REST client.
|
// ForwardResponseStream forwards the stream from gRPC server to REST client.
|
||||||
func ForwardResponseStream(ctx context.Context, marshaler Marshaler, w http.ResponseWriter, req *http.Request, recv func() (proto.Message, error), opts ...func(context.Context, http.ResponseWriter, proto.Message) error) {
|
func ForwardResponseStream(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, req *http.Request, recv func() (proto.Message, error), opts ...func(context.Context, http.ResponseWriter, proto.Message) error) {
|
||||||
f, ok := w.(http.Flusher)
|
f, ok := w.(http.Flusher)
|
||||||
if !ok {
|
if !ok {
|
||||||
grpclog.Printf("Flush not supported in %T", w)
|
grpclog.Printf("Flush not supported in %T", w)
|
||||||
@ -28,7 +29,7 @@ func ForwardResponseStream(ctx context.Context, marshaler Marshaler, w http.Resp
|
|||||||
http.Error(w, "unexpected error", http.StatusInternalServerError)
|
http.Error(w, "unexpected error", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
handleForwardResponseServerMetadata(w, md)
|
handleForwardResponseServerMetadata(w, mux, md)
|
||||||
|
|
||||||
w.Header().Set("Transfer-Encoding", "chunked")
|
w.Header().Set("Transfer-Encoding", "chunked")
|
||||||
w.Header().Set("Content-Type", marshaler.ContentType())
|
w.Header().Set("Content-Type", marshaler.ContentType())
|
||||||
@ -57,7 +58,7 @@ func ForwardResponseStream(ctx context.Context, marshaler Marshaler, w http.Resp
|
|||||||
grpclog.Printf("Failed to marshal response chunk: %v", err)
|
grpclog.Printf("Failed to marshal response chunk: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err = fmt.Fprintf(w, "%s\n", buf); err != nil {
|
if _, err = w.Write(buf); err != nil {
|
||||||
grpclog.Printf("Failed to send response chunk: %v", err)
|
grpclog.Printf("Failed to send response chunk: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -65,11 +66,12 @@ func ForwardResponseStream(ctx context.Context, marshaler Marshaler, w http.Resp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleForwardResponseServerMetadata(w http.ResponseWriter, md ServerMetadata) {
|
func handleForwardResponseServerMetadata(w http.ResponseWriter, mux *ServeMux, md ServerMetadata) {
|
||||||
for k, vs := range md.HeaderMD {
|
for k, vs := range md.HeaderMD {
|
||||||
hKey := fmt.Sprintf("%s%s", MetadataHeaderPrefix, k)
|
if h, ok := mux.outgoingHeaderMatcher(k); ok {
|
||||||
for i := range vs {
|
for _, v := range vs {
|
||||||
w.Header().Add(hKey, vs[i])
|
w.Header().Add(h, v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,31 +86,31 @@ func handleForwardResponseTrailerHeader(w http.ResponseWriter, md ServerMetadata
|
|||||||
func handleForwardResponseTrailer(w http.ResponseWriter, md ServerMetadata) {
|
func handleForwardResponseTrailer(w http.ResponseWriter, md ServerMetadata) {
|
||||||
for k, vs := range md.TrailerMD {
|
for k, vs := range md.TrailerMD {
|
||||||
tKey := fmt.Sprintf("%s%s", MetadataTrailerPrefix, k)
|
tKey := fmt.Sprintf("%s%s", MetadataTrailerPrefix, k)
|
||||||
for i := range vs {
|
for _, v := range vs {
|
||||||
w.Header().Add(tKey, vs[i])
|
w.Header().Add(tKey, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForwardResponseMessage forwards the message "resp" from gRPC server to REST client.
|
// ForwardResponseMessage forwards the message "resp" from gRPC server to REST client.
|
||||||
func ForwardResponseMessage(ctx context.Context, marshaler Marshaler, w http.ResponseWriter, req *http.Request, resp proto.Message, opts ...func(context.Context, http.ResponseWriter, proto.Message) error) {
|
func ForwardResponseMessage(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, req *http.Request, resp proto.Message, opts ...func(context.Context, http.ResponseWriter, proto.Message) error) {
|
||||||
md, ok := ServerMetadataFromContext(ctx)
|
md, ok := ServerMetadataFromContext(ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
grpclog.Printf("Failed to extract ServerMetadata from context")
|
grpclog.Printf("Failed to extract ServerMetadata from context")
|
||||||
}
|
}
|
||||||
|
|
||||||
handleForwardResponseServerMetadata(w, md)
|
handleForwardResponseServerMetadata(w, mux, md)
|
||||||
handleForwardResponseTrailerHeader(w, md)
|
handleForwardResponseTrailerHeader(w, md)
|
||||||
w.Header().Set("Content-Type", marshaler.ContentType())
|
w.Header().Set("Content-Type", marshaler.ContentType())
|
||||||
if err := handleForwardResponseOptions(ctx, w, resp, opts); err != nil {
|
if err := handleForwardResponseOptions(ctx, w, resp, opts); err != nil {
|
||||||
HTTPError(ctx, marshaler, w, req, err)
|
HTTPError(ctx, mux, marshaler, w, req, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
buf, err := marshaler.Marshal(resp)
|
buf, err := marshaler.Marshal(resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
grpclog.Printf("Marshal error: %v", err)
|
grpclog.Printf("Marshal error: %v", err)
|
||||||
HTTPError(ctx, marshaler, w, req, err)
|
HTTPError(ctx, mux, marshaler, w, req, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +148,10 @@ func handleForwardResponseStreamError(marshaler Marshaler, w http.ResponseWriter
|
|||||||
|
|
||||||
func streamChunk(result proto.Message, err error) map[string]proto.Message {
|
func streamChunk(result proto.Message, err error) map[string]proto.Message {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
grpcCode := grpc.Code(err)
|
grpcCode := codes.Unknown
|
||||||
|
if s, ok := status.FromError(err); ok {
|
||||||
|
grpcCode = s.Code()
|
||||||
|
}
|
||||||
httpCode := HTTPStatusFromCode(grpcCode)
|
httpCode := HTTPStatusFromCode(grpcCode)
|
||||||
return map[string]proto.Message{
|
return map[string]proto.Message{
|
||||||
"error": &internal.StreamError{
|
"error": &internal.StreamError{
|
||||||
|
33
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/internal/stream_chunk.pb.go
generated
vendored
33
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/internal/stream_chunk.pb.go
generated
vendored
@ -1,6 +1,5 @@
|
|||||||
// Code generated by protoc-gen-go.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// source: runtime/internal/stream_chunk.proto
|
// source: runtime/internal/stream_chunk.proto
|
||||||
// DO NOT EDIT!
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Package internal is a generated protocol buffer package.
|
Package internal is a generated protocol buffer package.
|
||||||
@ -42,6 +41,34 @@ func (m *StreamError) String() string { return proto.CompactTextStrin
|
|||||||
func (*StreamError) ProtoMessage() {}
|
func (*StreamError) ProtoMessage() {}
|
||||||
func (*StreamError) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
func (*StreamError) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
|
||||||
|
|
||||||
|
func (m *StreamError) GetGrpcCode() int32 {
|
||||||
|
if m != nil {
|
||||||
|
return m.GrpcCode
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StreamError) GetHttpCode() int32 {
|
||||||
|
if m != nil {
|
||||||
|
return m.HttpCode
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StreamError) GetMessage() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Message
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *StreamError) GetHttpStatus() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.HttpStatus
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
proto.RegisterType((*StreamError)(nil), "grpc.gateway.runtime.StreamError")
|
proto.RegisterType((*StreamError)(nil), "grpc.gateway.runtime.StreamError")
|
||||||
}
|
}
|
||||||
@ -50,7 +77,7 @@ func init() { proto.RegisterFile("runtime/internal/stream_chunk.proto", fileDesc
|
|||||||
|
|
||||||
var fileDescriptor0 = []byte{
|
var fileDescriptor0 = []byte{
|
||||||
// 181 bytes of a gzipped FileDescriptorProto
|
// 181 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x34, 0x8e, 0xbf, 0xee, 0x82, 0x30,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x34, 0x8e, 0xbf, 0xee, 0x82, 0x30,
|
||||||
0x14, 0x85, 0xd3, 0xdf, 0x1f, 0x85, 0xcb, 0x46, 0x1c, 0x9a, 0x38, 0x48, 0x74, 0x61, 0x82, 0xc1,
|
0x14, 0x85, 0xd3, 0xdf, 0x1f, 0x85, 0xcb, 0x46, 0x1c, 0x9a, 0x38, 0x48, 0x74, 0x61, 0x82, 0xc1,
|
||||||
0x37, 0xd0, 0xf8, 0x02, 0xb0, 0xb9, 0x90, 0x0a, 0x37, 0x40, 0x94, 0x96, 0xdc, 0x5e, 0x62, 0x5c,
|
0x37, 0xd0, 0xf8, 0x02, 0xb0, 0xb9, 0x90, 0x0a, 0x37, 0x40, 0x94, 0x96, 0xdc, 0x5e, 0x62, 0x5c,
|
||||||
0x7d, 0x72, 0xd3, 0x22, 0xe3, 0xf9, 0xbe, 0x73, 0x92, 0x03, 0x07, 0x9a, 0x34, 0xf7, 0x03, 0xe6,
|
0x7d, 0x72, 0xd3, 0x22, 0xe3, 0xf9, 0xbe, 0x73, 0x92, 0x03, 0x07, 0x9a, 0x34, 0xf7, 0x03, 0xe6,
|
||||||
|
144
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/mux.go
generated
vendored
144
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/mux.go
generated
vendored
@ -1,12 +1,16 @@
|
|||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/textproto"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/metadata"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A HandlerFunc handles a specific pair of path pattern and HTTP method.
|
// A HandlerFunc handles a specific pair of path pattern and HTTP method.
|
||||||
@ -19,6 +23,10 @@ type ServeMux struct {
|
|||||||
handlers map[string][]handler
|
handlers map[string][]handler
|
||||||
forwardResponseOptions []func(context.Context, http.ResponseWriter, proto.Message) error
|
forwardResponseOptions []func(context.Context, http.ResponseWriter, proto.Message) error
|
||||||
marshalers marshalerRegistry
|
marshalers marshalerRegistry
|
||||||
|
incomingHeaderMatcher HeaderMatcherFunc
|
||||||
|
outgoingHeaderMatcher HeaderMatcherFunc
|
||||||
|
metadataAnnotator func(context.Context, *http.Request) metadata.MD
|
||||||
|
protoErrorHandler ProtoErrorHandlerFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeMuxOption is an option that can be given to a ServeMux on construction.
|
// ServeMuxOption is an option that can be given to a ServeMux on construction.
|
||||||
@ -36,6 +44,64 @@ func WithForwardResponseOption(forwardResponseOption func(context.Context, http.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HeaderMatcherFunc checks whether a header key should be forwarded to/from gRPC context.
|
||||||
|
type HeaderMatcherFunc func(string) (string, bool)
|
||||||
|
|
||||||
|
// DefaultHeaderMatcher is used to pass http request headers to/from gRPC context. This adds permanent HTTP header
|
||||||
|
// keys (as specified by the IANA) to gRPC context with grpcgateway- prefix. HTTP headers that start with
|
||||||
|
// 'Grpc-Metadata-' are mapped to gRPC metadata after removing prefix 'Grpc-Metadata-'.
|
||||||
|
func DefaultHeaderMatcher(key string) (string, bool) {
|
||||||
|
key = textproto.CanonicalMIMEHeaderKey(key)
|
||||||
|
if isPermanentHTTPHeader(key) {
|
||||||
|
return MetadataPrefix + key, true
|
||||||
|
} else if strings.HasPrefix(key, MetadataHeaderPrefix) {
|
||||||
|
return key[len(MetadataHeaderPrefix):], true
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithIncomingHeaderMatcher returns a ServeMuxOption representing a headerMatcher for incoming request to gateway.
|
||||||
|
//
|
||||||
|
// This matcher will be called with each header in http.Request. If matcher returns true, that header will be
|
||||||
|
// passed to gRPC context. To transform the header before passing to gRPC context, matcher should return modified header.
|
||||||
|
func WithIncomingHeaderMatcher(fn HeaderMatcherFunc) ServeMuxOption {
|
||||||
|
return func(mux *ServeMux) {
|
||||||
|
mux.incomingHeaderMatcher = fn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithOutgoingHeaderMatcher returns a ServeMuxOption representing a headerMatcher for outgoing response from gateway.
|
||||||
|
//
|
||||||
|
// This matcher will be called with each header in response header metadata. If matcher returns true, that header will be
|
||||||
|
// passed to http response returned from gateway. To transform the header before passing to response,
|
||||||
|
// matcher should return modified header.
|
||||||
|
func WithOutgoingHeaderMatcher(fn HeaderMatcherFunc) ServeMuxOption {
|
||||||
|
return func(mux *ServeMux) {
|
||||||
|
mux.outgoingHeaderMatcher = fn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithMetadata returns a ServeMuxOption for passing metadata to a gRPC context.
|
||||||
|
//
|
||||||
|
// This can be used by services that need to read from http.Request and modify gRPC context. A common use case
|
||||||
|
// is reading token from cookie and adding it in gRPC context.
|
||||||
|
func WithMetadata(annotator func(context.Context, *http.Request) metadata.MD) ServeMuxOption {
|
||||||
|
return func(serveMux *ServeMux) {
|
||||||
|
serveMux.metadataAnnotator = annotator
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithProtoErrorHandler returns a ServeMuxOption for passing metadata to a gRPC context.
|
||||||
|
//
|
||||||
|
// This can be used to handle an error as general proto message defined by gRPC.
|
||||||
|
// The response including body and status is not backward compatible with the default error handler.
|
||||||
|
// When this option is used, HTTPError and OtherErrorHandler are overwritten on initialization.
|
||||||
|
func WithProtoErrorHandler(fn ProtoErrorHandlerFunc) ServeMuxOption {
|
||||||
|
return func(serveMux *ServeMux) {
|
||||||
|
serveMux.protoErrorHandler = fn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewServeMux returns a new ServeMux whose internal mapping is empty.
|
// NewServeMux returns a new ServeMux whose internal mapping is empty.
|
||||||
func NewServeMux(opts ...ServeMuxOption) *ServeMux {
|
func NewServeMux(opts ...ServeMuxOption) *ServeMux {
|
||||||
serveMux := &ServeMux{
|
serveMux := &ServeMux{
|
||||||
@ -47,6 +113,29 @@ func NewServeMux(opts ...ServeMuxOption) *ServeMux {
|
|||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
opt(serveMux)
|
opt(serveMux)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if serveMux.protoErrorHandler != nil {
|
||||||
|
HTTPError = serveMux.protoErrorHandler
|
||||||
|
// OtherErrorHandler is no longer used when protoErrorHandler is set.
|
||||||
|
// Overwritten by a special error handler to return Unknown.
|
||||||
|
OtherErrorHandler = func(w http.ResponseWriter, r *http.Request, _ string, _ int) {
|
||||||
|
ctx := context.Background()
|
||||||
|
_, outboundMarshaler := MarshalerForRequest(serveMux, r)
|
||||||
|
sterr := status.Error(codes.Unknown, "unexpected use of OtherErrorHandler")
|
||||||
|
serveMux.protoErrorHandler(ctx, serveMux, outboundMarshaler, w, r, sterr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if serveMux.incomingHeaderMatcher == nil {
|
||||||
|
serveMux.incomingHeaderMatcher = DefaultHeaderMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
if serveMux.outgoingHeaderMatcher == nil {
|
||||||
|
serveMux.outgoingHeaderMatcher = func(key string) (string, bool) {
|
||||||
|
return fmt.Sprintf("%s%s", MetadataHeaderPrefix, key), true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return serveMux
|
return serveMux
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,9 +146,17 @@ func (s *ServeMux) Handle(meth string, pat Pattern, h HandlerFunc) {
|
|||||||
|
|
||||||
// ServeHTTP dispatches the request to the first handler whose pattern matches to r.Method and r.Path.
|
// ServeHTTP dispatches the request to the first handler whose pattern matches to r.Method and r.Path.
|
||||||
func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
|
||||||
path := r.URL.Path
|
path := r.URL.Path
|
||||||
if !strings.HasPrefix(path, "/") {
|
if !strings.HasPrefix(path, "/") {
|
||||||
OtherErrorHandler(w, r, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
if s.protoErrorHandler != nil {
|
||||||
|
_, outboundMarshaler := MarshalerForRequest(s, r)
|
||||||
|
sterr := status.Error(codes.InvalidArgument, http.StatusText(http.StatusBadRequest))
|
||||||
|
s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, sterr)
|
||||||
|
} else {
|
||||||
|
OtherErrorHandler(w, r, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +164,13 @@ func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
l := len(components)
|
l := len(components)
|
||||||
var verb string
|
var verb string
|
||||||
if idx := strings.LastIndex(components[l-1], ":"); idx == 0 {
|
if idx := strings.LastIndex(components[l-1], ":"); idx == 0 {
|
||||||
OtherErrorHandler(w, r, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
if s.protoErrorHandler != nil {
|
||||||
|
_, outboundMarshaler := MarshalerForRequest(s, r)
|
||||||
|
sterr := status.Error(codes.Unimplemented, http.StatusText(http.StatusNotImplemented))
|
||||||
|
s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, sterr)
|
||||||
|
} else {
|
||||||
|
OtherErrorHandler(w, r, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
} else if idx > 0 {
|
} else if idx > 0 {
|
||||||
c := components[l-1]
|
c := components[l-1]
|
||||||
@ -77,7 +180,13 @@ func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
if override := r.Header.Get("X-HTTP-Method-Override"); override != "" && isPathLengthFallback(r) {
|
if override := r.Header.Get("X-HTTP-Method-Override"); override != "" && isPathLengthFallback(r) {
|
||||||
r.Method = strings.ToUpper(override)
|
r.Method = strings.ToUpper(override)
|
||||||
if err := r.ParseForm(); err != nil {
|
if err := r.ParseForm(); err != nil {
|
||||||
OtherErrorHandler(w, r, err.Error(), http.StatusBadRequest)
|
if s.protoErrorHandler != nil {
|
||||||
|
_, outboundMarshaler := MarshalerForRequest(s, r)
|
||||||
|
sterr := status.Error(codes.InvalidArgument, err.Error())
|
||||||
|
s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, sterr)
|
||||||
|
} else {
|
||||||
|
OtherErrorHandler(w, r, err.Error(), http.StatusBadRequest)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,17 +213,36 @@ func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
// X-HTTP-Method-Override is optional. Always allow fallback to POST.
|
// X-HTTP-Method-Override is optional. Always allow fallback to POST.
|
||||||
if isPathLengthFallback(r) {
|
if isPathLengthFallback(r) {
|
||||||
if err := r.ParseForm(); err != nil {
|
if err := r.ParseForm(); err != nil {
|
||||||
OtherErrorHandler(w, r, err.Error(), http.StatusBadRequest)
|
if s.protoErrorHandler != nil {
|
||||||
|
_, outboundMarshaler := MarshalerForRequest(s, r)
|
||||||
|
sterr := status.Error(codes.InvalidArgument, err.Error())
|
||||||
|
s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, sterr)
|
||||||
|
} else {
|
||||||
|
OtherErrorHandler(w, r, err.Error(), http.StatusBadRequest)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.h(w, r, pathParams)
|
h.h(w, r, pathParams)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
OtherErrorHandler(w, r, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
|
if s.protoErrorHandler != nil {
|
||||||
|
_, outboundMarshaler := MarshalerForRequest(s, r)
|
||||||
|
sterr := status.Error(codes.Unimplemented, http.StatusText(http.StatusMethodNotAllowed))
|
||||||
|
s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, sterr)
|
||||||
|
} else {
|
||||||
|
OtherErrorHandler(w, r, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OtherErrorHandler(w, r, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
|
||||||
|
if s.protoErrorHandler != nil {
|
||||||
|
_, outboundMarshaler := MarshalerForRequest(s, r)
|
||||||
|
sterr := status.Error(codes.Unimplemented, http.StatusText(http.StatusNotImplemented))
|
||||||
|
s.protoErrorHandler(ctx, s, outboundMarshaler, w, r, sterr)
|
||||||
|
} else {
|
||||||
|
OtherErrorHandler(w, r, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetForwardResponseOptions returns the ForwardResponseOptions associated with this ServeMux.
|
// GetForwardResponseOptions returns the ForwardResponseOptions associated with this ServeMux.
|
||||||
|
2
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/pattern.go
generated
vendored
2
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/pattern.go
generated
vendored
@ -21,7 +21,7 @@ type op struct {
|
|||||||
operand int
|
operand int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pattern is a template pattern of http request paths defined in third_party/googleapis/google/api/http.proto.
|
// Pattern is a template pattern of http request paths defined in github.com/googleapis/googleapis/google/api/http.proto.
|
||||||
type Pattern struct {
|
type Pattern struct {
|
||||||
// ops is a list of operations
|
// ops is a list of operations
|
||||||
ops []op
|
ops []op
|
||||||
|
61
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto_errors.go
generated
vendored
Normal file
61
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto_errors.go
generated
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package runtime
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/grpclog"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ProtoErrorHandlerFunc handles the error as a gRPC error generated via status package and replies to the request.
|
||||||
|
type ProtoErrorHandlerFunc func(context.Context, *ServeMux, Marshaler, http.ResponseWriter, *http.Request, error)
|
||||||
|
|
||||||
|
var _ ProtoErrorHandlerFunc = DefaultHTTPProtoErrorHandler
|
||||||
|
|
||||||
|
// DefaultHTTPProtoErrorHandler is an implementation of HTTPError.
|
||||||
|
// If "err" is an error from gRPC system, the function replies with the status code mapped by HTTPStatusFromCode.
|
||||||
|
// If otherwise, it replies with http.StatusInternalServerError.
|
||||||
|
//
|
||||||
|
// The response body returned by this function is a Status message marshaled by a Marshaler.
|
||||||
|
//
|
||||||
|
// Do not set this function to HTTPError variable directly, use WithProtoErrorHandler option instead.
|
||||||
|
func DefaultHTTPProtoErrorHandler(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, _ *http.Request, err error) {
|
||||||
|
// return Internal when Marshal failed
|
||||||
|
const fallback = `{"code": 13, "message": "failed to marshal error message"}`
|
||||||
|
|
||||||
|
w.Header().Del("Trailer")
|
||||||
|
w.Header().Set("Content-Type", marshaler.ContentType())
|
||||||
|
|
||||||
|
s, ok := status.FromError(err)
|
||||||
|
if !ok {
|
||||||
|
s = status.New(codes.Unknown, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, merr := marshaler.Marshal(s.Proto())
|
||||||
|
if merr != nil {
|
||||||
|
grpclog.Printf("Failed to marshal error message %q: %v", s.Proto(), merr)
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
if _, err := io.WriteString(w, fallback); err != nil {
|
||||||
|
grpclog.Printf("Failed to write response: %v", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
md, ok := ServerMetadataFromContext(ctx)
|
||||||
|
if !ok {
|
||||||
|
grpclog.Printf("Failed to extract ServerMetadata from context")
|
||||||
|
}
|
||||||
|
|
||||||
|
handleForwardResponseServerMetadata(w, mux, md)
|
||||||
|
handleForwardResponseTrailerHeader(w, md)
|
||||||
|
st := HTTPStatusFromCode(s.Code())
|
||||||
|
w.WriteHeader(st)
|
||||||
|
if _, err := w.Write(buf); err != nil {
|
||||||
|
grpclog.Printf("Failed to write response: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleForwardResponseTrailer(w, md)
|
||||||
|
}
|
165
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/query.go
generated
vendored
165
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/query.go
generated
vendored
@ -4,7 +4,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/grpc-ecosystem/grpc-gateway/utilities"
|
"github.com/grpc-ecosystem/grpc-gateway/utilities"
|
||||||
@ -38,31 +40,39 @@ func populateFieldValueFromPath(msg proto.Message, fieldPath []string, values []
|
|||||||
if m.Kind() != reflect.Ptr {
|
if m.Kind() != reflect.Ptr {
|
||||||
return fmt.Errorf("unexpected type %T: %v", msg, msg)
|
return fmt.Errorf("unexpected type %T: %v", msg, msg)
|
||||||
}
|
}
|
||||||
|
var props *proto.Properties
|
||||||
m = m.Elem()
|
m = m.Elem()
|
||||||
for i, fieldName := range fieldPath {
|
for i, fieldName := range fieldPath {
|
||||||
isLast := i == len(fieldPath)-1
|
isLast := i == len(fieldPath)-1
|
||||||
if !isLast && m.Kind() != reflect.Struct {
|
if !isLast && m.Kind() != reflect.Struct {
|
||||||
return fmt.Errorf("non-aggregate type in the mid of path: %s", strings.Join(fieldPath, "."))
|
return fmt.Errorf("non-aggregate type in the mid of path: %s", strings.Join(fieldPath, "."))
|
||||||
}
|
}
|
||||||
f := fieldByProtoName(m, fieldName)
|
var f reflect.Value
|
||||||
if !f.IsValid() {
|
var err error
|
||||||
|
f, props, err = fieldByProtoName(m, fieldName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if !f.IsValid() {
|
||||||
grpclog.Printf("field not found in %T: %s", msg, strings.Join(fieldPath, "."))
|
grpclog.Printf("field not found in %T: %s", msg, strings.Join(fieldPath, "."))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
switch f.Kind() {
|
switch f.Kind() {
|
||||||
case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, reflect.String, reflect.Uint32, reflect.Uint64:
|
case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64, reflect.String, reflect.Uint32, reflect.Uint64:
|
||||||
|
if !isLast {
|
||||||
|
return fmt.Errorf("unexpected nested field %s in %s", fieldPath[i+1], strings.Join(fieldPath[:i+1], "."))
|
||||||
|
}
|
||||||
m = f
|
m = f
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
// TODO(yugui) Support []byte
|
// TODO(yugui) Support []byte
|
||||||
if !isLast {
|
if !isLast {
|
||||||
return fmt.Errorf("unexpected repeated field in %s", strings.Join(fieldPath, "."))
|
return fmt.Errorf("unexpected repeated field in %s", strings.Join(fieldPath, "."))
|
||||||
}
|
}
|
||||||
return populateRepeatedField(f, values)
|
return populateRepeatedField(f, values, props)
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
if f.IsNil() {
|
if f.IsNil() {
|
||||||
m = reflect.New(f.Type().Elem())
|
m = reflect.New(f.Type().Elem())
|
||||||
f.Set(m)
|
f.Set(m.Convert(f.Type()))
|
||||||
}
|
}
|
||||||
m = f.Elem()
|
m = f.Elem()
|
||||||
continue
|
continue
|
||||||
@ -80,39 +90,127 @@ func populateFieldValueFromPath(msg proto.Message, fieldPath []string, values []
|
|||||||
default:
|
default:
|
||||||
grpclog.Printf("too many field values: %s", strings.Join(fieldPath, "."))
|
grpclog.Printf("too many field values: %s", strings.Join(fieldPath, "."))
|
||||||
}
|
}
|
||||||
return populateField(m, values[0])
|
return populateField(m, values[0], props)
|
||||||
}
|
}
|
||||||
|
|
||||||
// fieldByProtoName looks up a field whose corresponding protobuf field name is "name".
|
// fieldByProtoName looks up a field whose corresponding protobuf field name is "name".
|
||||||
// "m" must be a struct value. It returns zero reflect.Value if no such field found.
|
// "m" must be a struct value. It returns zero reflect.Value if no such field found.
|
||||||
func fieldByProtoName(m reflect.Value, name string) reflect.Value {
|
func fieldByProtoName(m reflect.Value, name string) (reflect.Value, *proto.Properties, error) {
|
||||||
props := proto.GetProperties(m.Type())
|
props := proto.GetProperties(m.Type())
|
||||||
|
|
||||||
|
// look up field name in oneof map
|
||||||
|
if op, ok := props.OneofTypes[name]; ok {
|
||||||
|
v := reflect.New(op.Type.Elem())
|
||||||
|
field := m.Field(op.Field)
|
||||||
|
if !field.IsNil() {
|
||||||
|
return reflect.Value{}, nil, fmt.Errorf("field already set for %s oneof", props.Prop[op.Field].OrigName)
|
||||||
|
}
|
||||||
|
field.Set(v)
|
||||||
|
return v.Elem().Field(0), op.Prop, nil
|
||||||
|
}
|
||||||
|
|
||||||
for _, p := range props.Prop {
|
for _, p := range props.Prop {
|
||||||
if p.OrigName == name {
|
if p.OrigName == name {
|
||||||
return m.FieldByName(p.Name)
|
return m.FieldByName(p.Name), p, nil
|
||||||
|
}
|
||||||
|
if p.JSONName == name {
|
||||||
|
return m.FieldByName(p.Name), p, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return reflect.Value{}
|
return reflect.Value{}, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func populateRepeatedField(f reflect.Value, values []string) error {
|
func populateRepeatedField(f reflect.Value, values []string, props *proto.Properties) error {
|
||||||
elemType := f.Type().Elem()
|
elemType := f.Type().Elem()
|
||||||
|
|
||||||
|
// is the destination field a slice of an enumeration type?
|
||||||
|
if enumValMap := proto.EnumValueMap(props.Enum); enumValMap != nil {
|
||||||
|
return populateFieldEnumRepeated(f, values, enumValMap)
|
||||||
|
}
|
||||||
|
|
||||||
conv, ok := convFromType[elemType.Kind()]
|
conv, ok := convFromType[elemType.Kind()]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("unsupported field type %s", elemType)
|
return fmt.Errorf("unsupported field type %s", elemType)
|
||||||
}
|
}
|
||||||
f.Set(reflect.MakeSlice(f.Type(), len(values), len(values)))
|
f.Set(reflect.MakeSlice(f.Type(), len(values), len(values)).Convert(f.Type()))
|
||||||
for i, v := range values {
|
for i, v := range values {
|
||||||
result := conv.Call([]reflect.Value{reflect.ValueOf(v)})
|
result := conv.Call([]reflect.Value{reflect.ValueOf(v)})
|
||||||
if err := result[1].Interface(); err != nil {
|
if err := result[1].Interface(); err != nil {
|
||||||
return err.(error)
|
return err.(error)
|
||||||
}
|
}
|
||||||
f.Index(i).Set(result[0])
|
f.Index(i).Set(result[0].Convert(f.Index(i).Type()))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func populateField(f reflect.Value, value string) error {
|
func populateField(f reflect.Value, value string, props *proto.Properties) error {
|
||||||
|
// Handle well known type
|
||||||
|
type wkt interface {
|
||||||
|
XXX_WellKnownType() string
|
||||||
|
}
|
||||||
|
if wkt, ok := f.Addr().Interface().(wkt); ok {
|
||||||
|
switch wkt.XXX_WellKnownType() {
|
||||||
|
case "Timestamp":
|
||||||
|
if value == "null" {
|
||||||
|
f.Field(0).SetInt(0)
|
||||||
|
f.Field(1).SetInt(0)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err := time.Parse(time.RFC3339Nano, value)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("bad Timestamp: %v", err)
|
||||||
|
}
|
||||||
|
f.Field(0).SetInt(int64(t.Unix()))
|
||||||
|
f.Field(1).SetInt(int64(t.Nanosecond()))
|
||||||
|
return nil
|
||||||
|
case "DoubleValue":
|
||||||
|
fallthrough
|
||||||
|
case "FloatValue":
|
||||||
|
float64Val, err := strconv.ParseFloat(value, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("bad DoubleValue: %s", value)
|
||||||
|
}
|
||||||
|
f.Field(0).SetFloat(float64Val)
|
||||||
|
return nil
|
||||||
|
case "Int64Value":
|
||||||
|
fallthrough
|
||||||
|
case "Int32Value":
|
||||||
|
int64Val, err := strconv.ParseInt(value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("bad DoubleValue: %s", value)
|
||||||
|
}
|
||||||
|
f.Field(0).SetInt(int64Val)
|
||||||
|
return nil
|
||||||
|
case "UInt64Value":
|
||||||
|
fallthrough
|
||||||
|
case "UInt32Value":
|
||||||
|
uint64Val, err := strconv.ParseUint(value, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("bad DoubleValue: %s", value)
|
||||||
|
}
|
||||||
|
f.Field(0).SetUint(uint64Val)
|
||||||
|
return nil
|
||||||
|
case "BoolValue":
|
||||||
|
if value == "true" {
|
||||||
|
f.Field(0).SetBool(true)
|
||||||
|
} else if value == "false" {
|
||||||
|
f.Field(0).SetBool(false)
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("bad BoolValue: %s", value)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
case "StringValue":
|
||||||
|
f.Field(0).SetString(value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// is the destination field an enumeration type?
|
||||||
|
if enumValMap := proto.EnumValueMap(props.Enum); enumValMap != nil {
|
||||||
|
return populateFieldEnum(f, value, enumValMap)
|
||||||
|
}
|
||||||
|
|
||||||
conv, ok := convFromType[f.Kind()]
|
conv, ok := convFromType[f.Kind()]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("unsupported field type %T", f)
|
return fmt.Errorf("unsupported field type %T", f)
|
||||||
@ -121,7 +219,48 @@ func populateField(f reflect.Value, value string) error {
|
|||||||
if err := result[1].Interface(); err != nil {
|
if err := result[1].Interface(); err != nil {
|
||||||
return err.(error)
|
return err.(error)
|
||||||
}
|
}
|
||||||
f.Set(result[0])
|
f.Set(result[0].Convert(f.Type()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convertEnum(value string, t reflect.Type, enumValMap map[string]int32) (reflect.Value, error) {
|
||||||
|
// see if it's an enumeration string
|
||||||
|
if enumVal, ok := enumValMap[value]; ok {
|
||||||
|
return reflect.ValueOf(enumVal).Convert(t), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for an integer that matches an enumeration value
|
||||||
|
eVal, err := strconv.Atoi(value)
|
||||||
|
if err != nil {
|
||||||
|
return reflect.Value{}, fmt.Errorf("%s is not a valid %s", value, t)
|
||||||
|
}
|
||||||
|
for _, v := range enumValMap {
|
||||||
|
if v == int32(eVal) {
|
||||||
|
return reflect.ValueOf(eVal).Convert(t), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return reflect.Value{}, fmt.Errorf("%s is not a valid %s", value, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func populateFieldEnum(f reflect.Value, value string, enumValMap map[string]int32) error {
|
||||||
|
cval, err := convertEnum(value, f.Type(), enumValMap)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.Set(cval)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func populateFieldEnumRepeated(f reflect.Value, values []string, enumValMap map[string]int32) error {
|
||||||
|
elemType := f.Type().Elem()
|
||||||
|
f.Set(reflect.MakeSlice(f.Type(), len(values), len(values)).Convert(f.Type()))
|
||||||
|
for i, v := range values {
|
||||||
|
result, err := convertEnum(v, elemType, enumValMap)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
f.Index(i).Set(result)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user