[VOL-4290] Voltha go library updates for gRPC migration
Change-Id: I1aa2774beb6b7ed7419bc45aeb53fcae8a8ecda0
diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/BUILD.bazel b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/BUILD.bazel
index 2086222..58b72b9 100644
--- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/BUILD.bazel
+++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/BUILD.bazel
@@ -27,11 +27,12 @@
deps = [
"//internal:go_default_library",
"//utilities:go_default_library",
+ "@com_github_golang_protobuf//descriptor:go_default_library_gen",
"@com_github_golang_protobuf//jsonpb:go_default_library_gen",
"@com_github_golang_protobuf//proto:go_default_library",
- "@com_github_golang_protobuf//protoc-gen-go/generator:go_default_library_gen",
"@go_googleapis//google/api:httpbody_go_proto",
"@io_bazel_rules_go//proto/wkt:any_go_proto",
+ "@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
"@io_bazel_rules_go//proto/wkt:duration_go_proto",
"@io_bazel_rules_go//proto/wkt:field_mask_go_proto",
"@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
@@ -48,6 +49,7 @@
size = "small",
srcs = [
"context_test.go",
+ "convert_test.go",
"errors_test.go",
"fieldmask_test.go",
"handler_test.go",
@@ -62,8 +64,8 @@
],
embed = [":go_default_library"],
deps = [
- "//examples/proto/examplepb:go_default_library",
"//internal:go_default_library",
+ "//runtime/internal/examplepb:go_default_library",
"//utilities:go_default_library",
"@com_github_golang_protobuf//jsonpb:go_default_library_gen",
"@com_github_golang_protobuf//proto:go_default_library",
@@ -76,7 +78,6 @@
"@io_bazel_rules_go//proto/wkt:struct_go_proto",
"@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
"@io_bazel_rules_go//proto/wkt:wrappers_go_proto",
- "@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//metadata:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/context.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/context.go
index 896057e..d8cbd4c 100644
--- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/context.go
+++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/context.go
@@ -9,10 +9,10 @@
"net/textproto"
"strconv"
"strings"
+ "sync"
"time"
"google.golang.org/grpc/codes"
- "google.golang.org/grpc/grpclog"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
)
@@ -57,19 +57,45 @@
a gRPC service.
*/
func AnnotateContext(ctx context.Context, mux *ServeMux, req *http.Request) (context.Context, error) {
+ ctx, md, err := annotateContext(ctx, mux, req)
+ if err != nil {
+ return nil, err
+ }
+ if md == nil {
+ return ctx, nil
+ }
+
+ return metadata.NewOutgoingContext(ctx, md), nil
+}
+
+// AnnotateIncomingContext adds context information such as metadata from the request.
+// Attach metadata as incoming context.
+func AnnotateIncomingContext(ctx context.Context, mux *ServeMux, req *http.Request) (context.Context, error) {
+ ctx, md, err := annotateContext(ctx, mux, req)
+ if err != nil {
+ return nil, err
+ }
+ if md == nil {
+ return ctx, nil
+ }
+
+ return metadata.NewIncomingContext(ctx, md), nil
+}
+
+func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request) (context.Context, metadata.MD, error) {
var pairs []string
timeout := DefaultContextTimeout
if tm := req.Header.Get(metadataGrpcTimeout); tm != "" {
var err error
timeout, err = timeoutDecode(tm)
if err != nil {
- return nil, status.Errorf(codes.InvalidArgument, "invalid grpc-timeout: %s", tm)
+ return nil, nil, status.Errorf(codes.InvalidArgument, "invalid grpc-timeout: %s", tm)
}
}
for key, vals := range req.Header {
+ key = textproto.CanonicalMIMEHeaderKey(key)
for _, val := range vals {
- key = textproto.CanonicalMIMEHeaderKey(key)
// For backwards-compatibility, pass through 'authorization' header with no prefix.
if key == "Authorization" {
pairs = append(pairs, "authorization", val)
@@ -80,7 +106,7 @@
if strings.HasSuffix(key, metadataHeaderBinarySuffix) {
b, err := decodeBinHeader(val)
if err != nil {
- return nil, status.Errorf(codes.InvalidArgument, "invalid binary header %s: %s", key, err)
+ return nil, nil, status.Errorf(codes.InvalidArgument, "invalid binary header %s: %s", key, err)
}
val = string(b)
@@ -102,8 +128,6 @@
} else {
pairs = append(pairs, strings.ToLower(xForwardedFor), fmt.Sprintf("%s, %s", fwd, remoteIP))
}
- } else {
- grpclog.Infof("invalid remote addr: %s", addr)
}
}
@@ -111,13 +135,13 @@
ctx, _ = context.WithTimeout(ctx, timeout)
}
if len(pairs) == 0 {
- return ctx, nil
+ return ctx, nil, nil
}
md := metadata.Pairs(pairs...)
for _, mda := range mux.metadataAnnotators {
md = metadata.Join(md, mda(ctx, req))
}
- return metadata.NewOutgoingContext(ctx, md), nil
+ return ctx, md, nil
}
// ServerMetadata consists of metadata sent from gRPC server.
@@ -139,6 +163,63 @@
return
}
+// ServerTransportStream implements grpc.ServerTransportStream.
+// It should only be used by the generated files to support grpc.SendHeader
+// outside of gRPC server use.
+type ServerTransportStream struct {
+ mu sync.Mutex
+ header metadata.MD
+ trailer metadata.MD
+}
+
+// Method returns the method for the stream.
+func (s *ServerTransportStream) Method() string {
+ return ""
+}
+
+// Header returns the header metadata of the stream.
+func (s *ServerTransportStream) Header() metadata.MD {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.header.Copy()
+}
+
+// SetHeader sets the header metadata.
+func (s *ServerTransportStream) SetHeader(md metadata.MD) error {
+ if md.Len() == 0 {
+ return nil
+ }
+
+ s.mu.Lock()
+ s.header = metadata.Join(s.header, md)
+ s.mu.Unlock()
+ return nil
+}
+
+// SendHeader sets the header metadata.
+func (s *ServerTransportStream) SendHeader(md metadata.MD) error {
+ return s.SetHeader(md)
+}
+
+// Trailer returns the cached trailer metadata.
+func (s *ServerTransportStream) Trailer() metadata.MD {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.trailer.Copy()
+}
+
+// SetTrailer sets the trailer metadata.
+func (s *ServerTransportStream) SetTrailer(md metadata.MD) error {
+ if md.Len() == 0 {
+ return nil
+ }
+
+ s.mu.Lock()
+ s.trailer = metadata.Join(s.trailer, md)
+ s.mu.Unlock()
+ return nil
+}
+
func timeoutDecode(s string) (time.Duration, error) {
size := len(s)
if size < 2 {
@@ -175,7 +256,7 @@
}
// isPermanentHTTPHeader checks whether hdr belongs to the list of
-// permenant request headers maintained by IANA.
+// permanent request headers maintained by IANA.
// http://www.iana.org/assignments/message-headers/message-headers.xml
func isPermanentHTTPHeader(hdr string) bool {
switch hdr {
diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/convert.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/convert.go
index a5b3bd6..2c27934 100644
--- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/convert.go
+++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/convert.go
@@ -206,16 +206,22 @@
// Timestamp converts the given RFC3339 formatted string into a timestamp.Timestamp.
func Timestamp(val string) (*timestamp.Timestamp, error) {
- var r *timestamp.Timestamp
- err := jsonpb.UnmarshalString(val, r)
- return r, err
+ var r timestamp.Timestamp
+ err := jsonpb.UnmarshalString(val, &r)
+ if err != nil {
+ return nil, err
+ }
+ return &r, nil
}
// Duration converts the given string into a timestamp.Duration.
func Duration(val string) (*duration.Duration, error) {
- var r *duration.Duration
- err := jsonpb.UnmarshalString(val, r)
- return r, err
+ var r duration.Duration
+ err := jsonpb.UnmarshalString(val, &r)
+ if err != nil {
+ return nil, err
+ }
+ return &r, nil
}
// Enum converts the given string into an int32 that should be type casted into the
diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/errors.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/errors.go
index ad94578..b2ce743 100644
--- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/errors.go
+++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/errors.go
@@ -4,9 +4,9 @@
"context"
"io"
"net/http"
+ "strings"
- "github.com/golang/protobuf/proto"
- "github.com/golang/protobuf/ptypes/any"
+ "github.com/grpc-ecosystem/grpc-gateway/internal"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/status"
@@ -58,35 +58,59 @@
}
var (
- // HTTPError replies to the request with the error.
+ // HTTPError replies to the request with an error.
+ //
+ // HTTPError is called:
+ // - From generated per-endpoint gateway handler code, when calling the backend results in an error.
+ // - From gateway runtime code, when forwarding the response message results in an error.
+ //
+ // The default value for HTTPError calls the custom error handler configured on the ServeMux via the
+ // WithProtoErrorHandler serve option if that option was used, calling GlobalHTTPErrorHandler otherwise.
+ //
+ // To customize the error handling of a particular ServeMux instance, use the WithProtoErrorHandler
+ // serve option.
+ //
+ // To customize the error format for all ServeMux instances not using the WithProtoErrorHandler serve
+ // option, set GlobalHTTPErrorHandler to a custom function.
+ //
+ // Setting this variable directly to customize error format is deprecated.
+ HTTPError = MuxOrGlobalHTTPError
+
+ // GlobalHTTPErrorHandler is the HTTPError handler for all ServeMux instances not using the
+ // WithProtoErrorHandler serve option.
+ //
// You can set a custom function to this variable to customize error format.
- HTTPError = DefaultHTTPError
- // OtherErrorHandler handles the following error used by the gateway: StatusMethodNotAllowed StatusNotFound and StatusBadRequest
+ GlobalHTTPErrorHandler = DefaultHTTPError
+
+ // OtherErrorHandler handles gateway errors from parsing and routing client requests for all
+ // ServeMux instances not using the WithProtoErrorHandler serve option.
+ //
+ // It returns the following error codes: StatusMethodNotAllowed StatusNotFound StatusBadRequest
+ //
+ // To customize parsing and routing error handling of a particular ServeMux instance, use the
+ // WithProtoErrorHandler serve option.
+ //
+ // To customize parsing and routing error handling of all ServeMux instances not using the
+ // WithProtoErrorHandler serve option, set a custom function to this variable.
OtherErrorHandler = DefaultOtherErrorHandler
)
-type errorBody struct {
- Error string `protobuf:"bytes,1,name=error" json:"error"`
- // This is to make the error more compatible with users that expect errors to be Status objects:
- // https://github.com/grpc/grpc/blob/master/src/proto/grpc/status/status.proto
- // It should be the exact same message as the Error field.
- Message string `protobuf:"bytes,1,name=message" json:"message"`
- Code int32 `protobuf:"varint,2,name=code" json:"code"`
- Details []*any.Any `protobuf:"bytes,3,rep,name=details" json:"details,omitempty"`
+// MuxOrGlobalHTTPError uses the mux-configured error handler, falling back to GlobalErrorHandler.
+func MuxOrGlobalHTTPError(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, r *http.Request, err error) {
+ if mux.protoErrorHandler != nil {
+ mux.protoErrorHandler(ctx, mux, marshaler, w, r, err)
+ } else {
+ GlobalHTTPErrorHandler(ctx, mux, marshaler, w, r, err)
+ }
}
-// Make this also conform to proto.Message for builtin JSONPb Marshaler
-func (e *errorBody) Reset() { *e = errorBody{} }
-func (e *errorBody) String() string { return proto.CompactTextString(e) }
-func (*errorBody) ProtoMessage() {}
-
// DefaultHTTPError is the default 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 JSON object,
// which contains a member whose key is "error" and whose value is err.Error().
-func DefaultHTTPError(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, _ *http.Request, err error) {
+func DefaultHTTPError(ctx context.Context, mux *ServeMux, marshaler Marshaler, w http.ResponseWriter, r *http.Request, err error) {
const fallback = `{"error": "failed to marshal error message"}`
s, ok := status.FromError(err)
@@ -95,18 +119,19 @@
}
w.Header().Del("Trailer")
+ w.Header().Del("Transfer-Encoding")
contentType := marshaler.ContentType()
- // Check marshaler on run time in order to keep backwards compatability
+ // Check marshaler on run time in order to keep backwards compatibility
// An interface param needs to be added to the ContentType() function on
// the Marshal interface to be able to remove this check
- if httpBodyMarshaler, ok := marshaler.(*HTTPBodyMarshaler); ok {
+ if typeMarshaler, ok := marshaler.(contentTypeMarshaler); ok {
pb := s.Proto()
- contentType = httpBodyMarshaler.ContentTypeFromMessage(pb)
+ contentType = typeMarshaler.ContentTypeFromMessage(pb)
}
w.Header().Set("Content-Type", contentType)
- body := &errorBody{
+ body := &internal.Error{
Error: s.Message(),
Message: s.Message(),
Code: int32(s.Code()),
@@ -129,14 +154,29 @@
}
handleForwardResponseServerMetadata(w, mux, md)
- handleForwardResponseTrailerHeader(w, md)
+
+ // RFC 7230 https://tools.ietf.org/html/rfc7230#section-4.1.2
+ // Unless the request includes a TE header field indicating "trailers"
+ // is acceptable, as described in Section 4.3, a server SHOULD NOT
+ // generate trailer fields that it believes are necessary for the user
+ // agent to receive.
+ var wantsTrailers bool
+
+ if te := r.Header.Get("TE"); strings.Contains(strings.ToLower(te), "trailers") {
+ wantsTrailers = true
+ handleForwardResponseTrailerHeader(w, md)
+ w.Header().Set("Transfer-Encoding", "chunked")
+ }
+
st := HTTPStatusFromCode(s.Code())
w.WriteHeader(st)
if _, err := w.Write(buf); err != nil {
grpclog.Infof("Failed to write response: %v", err)
}
- handleForwardResponseTrailer(w, md)
+ if wantsTrailers {
+ handleForwardResponseTrailer(w, md)
+ }
}
// DefaultOtherErrorHandler is the default implementation of OtherErrorHandler.
diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/fieldmask.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/fieldmask.go
index e1cf7a9..aef645e 100644
--- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/fieldmask.go
+++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/fieldmask.go
@@ -5,12 +5,37 @@
"io"
"strings"
- "github.com/golang/protobuf/protoc-gen-go/generator"
+ descriptor2 "github.com/golang/protobuf/descriptor"
+ "github.com/golang/protobuf/protoc-gen-go/descriptor"
"google.golang.org/genproto/protobuf/field_mask"
)
+func translateName(name string, md *descriptor.DescriptorProto) (string, *descriptor.DescriptorProto) {
+ // TODO - should really gate this with a test that the marshaller has used json names
+ if md != nil {
+ for _, f := range md.Field {
+ if f.JsonName != nil && f.Name != nil && *f.JsonName == name {
+ var subType *descriptor.DescriptorProto
+
+ // If the field has a TypeName then we retrieve the nested type for translating the embedded message names.
+ if f.TypeName != nil {
+ typeSplit := strings.Split(*f.TypeName, ".")
+ typeName := typeSplit[len(typeSplit)-1]
+ for _, t := range md.NestedType {
+ if typeName == *t.Name {
+ subType = t
+ }
+ }
+ }
+ return *f.Name, subType
+ }
+ }
+ }
+ return name, nil
+}
+
// FieldMaskFromRequestBody creates a FieldMask printing all complete paths from the JSON body.
-func FieldMaskFromRequestBody(r io.Reader) (*field_mask.FieldMask, error) {
+func FieldMaskFromRequestBody(r io.Reader, md *descriptor.DescriptorProto) (*field_mask.FieldMask, error) {
fm := &field_mask.FieldMask{}
var root interface{}
if err := json.NewDecoder(r).Decode(&root); err != nil {
@@ -20,7 +45,7 @@
return nil, err
}
- queue := []fieldMaskPathItem{{node: root}}
+ queue := []fieldMaskPathItem{{node: root, md: md}}
for len(queue) > 0 {
// dequeue an item
item := queue[0]
@@ -29,11 +54,22 @@
if m, ok := item.node.(map[string]interface{}); ok {
// if the item is an object, then enqueue all of its children
for k, v := range m {
- queue = append(queue, fieldMaskPathItem{path: append(item.path, generator.CamelCase(k)), node: v})
+ protoName, subMd := translateName(k, item.md)
+ if subMsg, ok := v.(descriptor2.Message); ok {
+ _, subMd = descriptor2.ForMessage(subMsg)
+ }
+
+ var path string
+ if item.path == "" {
+ path = protoName
+ } else {
+ path = item.path + "." + protoName
+ }
+ queue = append(queue, fieldMaskPathItem{path: path, node: v, md: subMd})
}
} else if len(item.path) > 0 {
// otherwise, it's a leaf node so print its path
- fm.Paths = append(fm.Paths, strings.Join(item.path, "."))
+ fm.Paths = append(fm.Paths, item.path)
}
}
@@ -42,29 +78,12 @@
// fieldMaskPathItem stores a in-progress deconstruction of a path for a fieldmask
type fieldMaskPathItem struct {
- // the list of prior fields leading up to node
- path []string
+ // the list of prior fields leading up to node connected by dots
+ path string
// a generic decoded json object the current item to inspect for further path extraction
node interface{}
-}
-// CamelCaseFieldMask updates the given FieldMask by converting all of its paths to CamelCase, using the same heuristic
-// that's used for naming protobuf fields in Go.
-func CamelCaseFieldMask(mask *field_mask.FieldMask) {
- if mask == nil || mask.Paths == nil {
- return
- }
-
- var newPaths []string
- for _, path := range mask.Paths {
- lowerCasedParts := strings.Split(path, ".")
- var camelCasedParts []string
- for _, part := range lowerCasedParts {
- camelCasedParts = append(camelCasedParts, generator.CamelCase(part))
- }
- newPaths = append(newPaths, strings.Join(camelCasedParts, "."))
- }
-
- mask.Paths = newPaths
+ // descriptor for parent message
+ md *descriptor.DescriptorProto
}
diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/handler.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/handler.go
index 2af9006..e6e8f28 100644
--- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/handler.go
+++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/handler.go
@@ -1,13 +1,13 @@
package runtime
import (
+ "context"
"errors"
"fmt"
"io"
"net/http"
"net/textproto"
- "context"
"github.com/golang/protobuf/proto"
"github.com/grpc-ecosystem/grpc-gateway/internal"
"google.golang.org/grpc/grpclog"
@@ -61,7 +61,19 @@
return
}
- buf, err := marshaler.Marshal(streamChunk(ctx, resp, mux.streamErrorHandler))
+ var buf []byte
+ switch {
+ case resp == nil:
+ buf, err = marshaler.Marshal(errorChunk(streamError(ctx, mux.streamErrorHandler, errEmptyResponse)))
+ default:
+ result := map[string]interface{}{"result": resp}
+ if rb, ok := resp.(responseBody); ok {
+ result["result"] = rb.XXX_ResponseBody()
+ }
+
+ buf, err = marshaler.Marshal(result)
+ }
+
if err != nil {
grpclog.Infof("Failed to marshal response chunk: %v", err)
handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err)
@@ -123,11 +135,11 @@
handleForwardResponseTrailerHeader(w, md)
contentType := marshaler.ContentType()
- // Check marshaler on run time in order to keep backwards compatability
+ // Check marshaler on run time in order to keep backwards compatibility
// An interface param needs to be added to the ContentType() function on
// the Marshal interface to be able to remove this check
- if httpBodyMarshaler, ok := marshaler.(*HTTPBodyMarshaler); ok {
- contentType = httpBodyMarshaler.ContentTypeFromMessage(resp)
+ if typeMarshaler, ok := marshaler.(contentTypeMarshaler); ok {
+ contentType = typeMarshaler.ContentTypeFromMessage(resp)
}
w.Header().Set("Content-Type", contentType)
@@ -184,15 +196,6 @@
}
}
-// streamChunk returns a chunk in a response stream for the given result. The
-// given errHandler is used to render an error chunk if result is nil.
-func streamChunk(ctx context.Context, result proto.Message, errHandler StreamErrorHandlerFunc) map[string]proto.Message {
- if result == nil {
- return errorChunk(streamError(ctx, errHandler, errEmptyResponse))
- }
- return map[string]proto.Message{"result": result}
-}
-
// streamError returns the payload for the final message in a response stream
// that represents the given err.
func streamError(ctx context.Context, errHandler StreamErrorHandlerFunc, err error) *StreamError {
diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_httpbodyproto.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_httpbodyproto.go
index f55285b..525b033 100644
--- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_httpbodyproto.go
+++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshal_httpbodyproto.go
@@ -19,7 +19,7 @@
Marshaler
}
-// ContentType implementation to keep backwards compatability with marshal interface
+// ContentType implementation to keep backwards compatibility with marshal interface
func (h *HTTPBodyMarshaler) ContentType() string {
return h.ContentTypeFromMessage(nil)
}
diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler.go
index 98fe6e8..4615329 100644
--- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler.go
+++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler.go
@@ -19,6 +19,13 @@
ContentType() string
}
+// Marshalers that implement contentTypeMarshaler will have their ContentTypeFromMessage method called
+// to set the Content-Type header on the response
+type contentTypeMarshaler interface {
+ // ContentTypeFromMessage returns the Content-Type this marshaler produces from the provided message
+ ContentTypeFromMessage(v interface{}) string
+}
+
// Decoder decodes a byte sequence
type Decoder interface {
Decode(v interface{}) error
@@ -43,6 +50,6 @@
// Delimited defines the streaming delimiter.
type Delimited interface {
- // Delimiter returns the record seperator for the stream.
+ // Delimiter returns the record separator for the stream.
Delimiter() []byte
}
diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler_registry.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler_registry.go
index 5cc53ae..8dd5c24 100644
--- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler_registry.go
+++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/marshaler_registry.go
@@ -2,7 +2,10 @@
import (
"errors"
+ "mime"
"net/http"
+
+ "google.golang.org/grpc/grpclog"
)
// MIMEWildcard is the fallback MIME type used for requests which do not match
@@ -31,7 +34,12 @@
}
for _, contentTypeVal := range r.Header[contentTypeHeader] {
- if m, ok := mux.marshalers.mimeMap[contentTypeVal]; ok {
+ contentType, _, err := mime.ParseMediaType(contentTypeVal)
+ if err != nil {
+ grpclog.Infof("Failed to parse Content-Type %s: %v", contentTypeVal, err)
+ continue
+ }
+ if m, ok := mux.marshalers.mimeMap[contentType]; ok {
inbound = m
break
}
diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/mux.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/mux.go
index 1da3a58..523a9cb 100644
--- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/mux.go
+++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/mux.go
@@ -55,6 +55,15 @@
}
}
+// SetQueryParameterParser sets the query parameter parser, used to populate message from query parameters.
+// Configuring this will mean the generated swagger output is no longer correct, and it should be
+// done with careful consideration.
+func SetQueryParameterParser(queryParameterParser QueryParameterParser) ServeMuxOption {
+ return func(serveMux *ServeMux) {
+ currentQueryParser = queryParameterParser
+ }
+}
+
// HeaderMatcherFunc checks whether a header key should be forwarded to/from gRPC context.
type HeaderMatcherFunc func(string) (string, bool)
@@ -102,11 +111,11 @@
}
}
-// WithProtoErrorHandler returns a ServeMuxOption for passing metadata to a gRPC context.
+// WithProtoErrorHandler returns a ServeMuxOption for configuring a custom error handler.
//
// 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.
+// When this option is used, the mux uses the configured error handler instead of HTTPError and
+// OtherErrorHandler.
func WithProtoErrorHandler(fn ProtoErrorHandlerFunc) ServeMuxOption {
return func(serveMux *ServeMux) {
serveMux.protoErrorHandler = fn
@@ -156,18 +165,6 @@
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
}
diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto_errors.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto_errors.go
index ca76324..3fd30da 100644
--- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto_errors.go
+++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto_errors.go
@@ -44,12 +44,12 @@
w.Header().Del("Trailer")
contentType := marshaler.ContentType()
- // Check marshaler on run time in order to keep backwards compatability
+ // Check marshaler on run time in order to keep backwards compatibility
// An interface param needs to be added to the ContentType() function on
// the Marshal interface to be able to remove this check
- if httpBodyMarshaler, ok := marshaler.(*HTTPBodyMarshaler); ok {
+ if typeMarshaler, ok := marshaler.(contentTypeMarshaler); ok {
pb := s.Proto()
- contentType = httpBodyMarshaler.ContentTypeFromMessage(pb)
+ contentType = typeMarshaler.ContentTypeFromMessage(pb)
}
w.Header().Set("Content-Type", contentType)
diff --git a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/query.go b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/query.go
index 5fbba5e..ba66842 100644
--- a/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/query.go
+++ b/vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/query.go
@@ -15,15 +15,28 @@
"google.golang.org/grpc/grpclog"
)
-// PopulateQueryParameters populates "values" into "msg".
-// A value is ignored if its key starts with one of the elements in "filter".
+var valuesKeyRegexp = regexp.MustCompile("^(.*)\\[(.*)\\]$")
+
+var currentQueryParser QueryParameterParser = &defaultQueryParser{}
+
+// QueryParameterParser defines interface for all query parameter parsers
+type QueryParameterParser interface {
+ Parse(msg proto.Message, values url.Values, filter *utilities.DoubleArray) error
+}
+
+// PopulateQueryParameters parses query parameters
+// into "msg" using current query parser
func PopulateQueryParameters(msg proto.Message, values url.Values, filter *utilities.DoubleArray) error {
+ return currentQueryParser.Parse(msg, values, filter)
+}
+
+type defaultQueryParser struct{}
+
+// Parse populates "values" into "msg".
+// A value is ignored if its key starts with one of the elements in "filter".
+func (*defaultQueryParser) Parse(msg proto.Message, values url.Values, filter *utilities.DoubleArray) error {
for key, values := range values {
- re, err := regexp.Compile("^(.*)\\[(.*)\\]$")
- if err != nil {
- return err
- }
- match := re.FindStringSubmatch(key)
+ match := valuesKeyRegexp.FindStringSubmatch(key)
if len(match) == 3 {
key = match[1]
values = append([]string{match[2]}, values...)
@@ -119,14 +132,16 @@
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)
+ for _, op := range props.OneofTypes {
+ if name == op.Prop.OrigName || name == op.Prop.JSONName {
+ 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
}
- field.Set(v)
- return v.Elem().Field(0), op.Prop, nil
}
for _, p := range props.Prop {