mirror of https://github.com/docker/cli.git
vendor: github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0
full diff: https://github.com/grpc-ecosystem/grpc-gateway/compare/v2.16.0...v2.20.0 Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
f3cf1b4213
commit
9ba73a1a05
|
@ -73,7 +73,7 @@ require (
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/gorilla/mux v1.8.1 // indirect
|
github.com/gorilla/mux v1.8.1 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/klauspost/compress v1.17.11 // indirect
|
github.com/klauspost/compress v1.17.11 // indirect
|
||||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||||
|
|
|
@ -96,8 +96,6 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY=
|
|
||||||
github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
@ -117,8 +115,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3
|
||||||
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
|
||||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
|
||||||
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
|
|
@ -24,7 +24,7 @@ go_test(
|
||||||
embed = [":httprule"],
|
embed = [":httprule"],
|
||||||
deps = [
|
deps = [
|
||||||
"//utilities",
|
"//utilities",
|
||||||
"@com_github_golang_glog//:glog",
|
"@org_golang_google_grpc//grpclog",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ go_library(
|
||||||
deps = [
|
deps = [
|
||||||
"//internal/httprule",
|
"//internal/httprule",
|
||||||
"//utilities",
|
"//utilities",
|
||||||
"@go_googleapis//google/api:httpbody_go_proto",
|
"@org_golang_google_genproto_googleapis_api//httpbody",
|
||||||
"@org_golang_google_grpc//codes",
|
"@org_golang_google_grpc//codes",
|
||||||
"@org_golang_google_grpc//grpclog",
|
"@org_golang_google_grpc//grpclog",
|
||||||
"@org_golang_google_grpc//health/grpc_health_v1",
|
"@org_golang_google_grpc//health/grpc_health_v1",
|
||||||
|
@ -70,9 +70,9 @@ go_test(
|
||||||
"//utilities",
|
"//utilities",
|
||||||
"@com_github_google_go_cmp//cmp",
|
"@com_github_google_go_cmp//cmp",
|
||||||
"@com_github_google_go_cmp//cmp/cmpopts",
|
"@com_github_google_go_cmp//cmp/cmpopts",
|
||||||
"@go_googleapis//google/api:httpbody_go_proto",
|
"@org_golang_google_genproto_googleapis_api//httpbody",
|
||||||
"@go_googleapis//google/rpc:errdetails_go_proto",
|
"@org_golang_google_genproto_googleapis_rpc//errdetails",
|
||||||
"@go_googleapis//google/rpc:status_go_proto",
|
"@org_golang_google_genproto_googleapis_rpc//status",
|
||||||
"@org_golang_google_grpc//:go_default_library",
|
"@org_golang_google_grpc//:go_default_library",
|
||||||
"@org_golang_google_grpc//codes",
|
"@org_golang_google_grpc//codes",
|
||||||
"@org_golang_google_grpc//health/grpc_health_v1",
|
"@org_golang_google_grpc//health/grpc_health_v1",
|
||||||
|
|
|
@ -148,6 +148,12 @@ func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcM
|
||||||
var pairs []string
|
var pairs []string
|
||||||
for key, vals := range req.Header {
|
for key, vals := range req.Header {
|
||||||
key = textproto.CanonicalMIMEHeaderKey(key)
|
key = textproto.CanonicalMIMEHeaderKey(key)
|
||||||
|
switch key {
|
||||||
|
case xForwardedFor, xForwardedHost:
|
||||||
|
// Handled separately below
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
for _, val := range vals {
|
for _, val := range vals {
|
||||||
// For backwards-compatibility, pass through 'authorization' header with no prefix.
|
// For backwards-compatibility, pass through 'authorization' header with no prefix.
|
||||||
if key == "Authorization" {
|
if key == "Authorization" {
|
||||||
|
@ -181,18 +187,17 @@ func annotateContext(ctx context.Context, mux *ServeMux, req *http.Request, rpcM
|
||||||
pairs = append(pairs, strings.ToLower(xForwardedHost), req.Host)
|
pairs = append(pairs, strings.ToLower(xForwardedHost), req.Host)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xff := req.Header.Values(xForwardedFor)
|
||||||
if addr := req.RemoteAddr; addr != "" {
|
if addr := req.RemoteAddr; addr != "" {
|
||||||
if remoteIP, _, err := net.SplitHostPort(addr); err == nil {
|
if remoteIP, _, err := net.SplitHostPort(addr); err == nil {
|
||||||
if fwd := req.Header.Get(xForwardedFor); fwd == "" {
|
xff = append(xff, remoteIP)
|
||||||
pairs = append(pairs, strings.ToLower(xForwardedFor), remoteIP)
|
|
||||||
} else {
|
|
||||||
pairs = append(pairs, strings.ToLower(xForwardedFor), fmt.Sprintf("%s, %s", fwd, remoteIP))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(xff) > 0 {
|
||||||
|
pairs = append(pairs, strings.ToLower(xForwardedFor), strings.Join(xff, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
if timeout != 0 {
|
if timeout != 0 {
|
||||||
//nolint:govet // The context outlives this function
|
|
||||||
ctx, _ = context.WithTimeout(ctx, timeout)
|
ctx, _ = context.WithTimeout(ctx, timeout)
|
||||||
}
|
}
|
||||||
if len(pairs) == 0 {
|
if len(pairs) == 0 {
|
||||||
|
|
|
@ -71,7 +71,7 @@ func HTTPStatusFromCode(code codes.Code) int {
|
||||||
case codes.DataLoss:
|
case codes.DataLoss:
|
||||||
return http.StatusInternalServerError
|
return http.StatusInternalServerError
|
||||||
default:
|
default:
|
||||||
grpclog.Infof("Unknown gRPC error code: %v", code)
|
grpclog.Warningf("Unknown gRPC error code: %v", code)
|
||||||
return http.StatusInternalServerError
|
return http.StatusInternalServerError
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,17 +114,17 @@ func DefaultHTTPErrorHandler(ctx context.Context, mux *ServeMux, marshaler Marsh
|
||||||
|
|
||||||
buf, merr := marshaler.Marshal(pb)
|
buf, merr := marshaler.Marshal(pb)
|
||||||
if merr != nil {
|
if merr != nil {
|
||||||
grpclog.Infof("Failed to marshal error message %q: %v", s, merr)
|
grpclog.Errorf("Failed to marshal error message %q: %v", s, merr)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
if _, err := io.WriteString(w, fallback); err != nil {
|
if _, err := io.WriteString(w, fallback); err != nil {
|
||||||
grpclog.Infof("Failed to write response: %v", err)
|
grpclog.Errorf("Failed to write response: %v", err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
md, ok := ServerMetadataFromContext(ctx)
|
md, ok := ServerMetadataFromContext(ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
grpclog.Infof("Failed to extract ServerMetadata from context")
|
grpclog.Error("Failed to extract ServerMetadata from context")
|
||||||
}
|
}
|
||||||
|
|
||||||
handleForwardResponseServerMetadata(w, mux, md)
|
handleForwardResponseServerMetadata(w, mux, md)
|
||||||
|
@ -137,7 +137,7 @@ func DefaultHTTPErrorHandler(ctx context.Context, mux *ServeMux, marshaler Marsh
|
||||||
doForwardTrailers := requestAcceptsTrailers(r)
|
doForwardTrailers := requestAcceptsTrailers(r)
|
||||||
|
|
||||||
if doForwardTrailers {
|
if doForwardTrailers {
|
||||||
handleForwardResponseTrailerHeader(w, md)
|
handleForwardResponseTrailerHeader(w, mux, md)
|
||||||
w.Header().Set("Transfer-Encoding", "chunked")
|
w.Header().Set("Transfer-Encoding", "chunked")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,11 +148,11 @@ func DefaultHTTPErrorHandler(ctx context.Context, mux *ServeMux, marshaler Marsh
|
||||||
|
|
||||||
w.WriteHeader(st)
|
w.WriteHeader(st)
|
||||||
if _, err := w.Write(buf); err != nil {
|
if _, err := w.Write(buf); err != nil {
|
||||||
grpclog.Infof("Failed to write response: %v", err)
|
grpclog.Errorf("Failed to write response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if doForwardTrailers {
|
if doForwardTrailers {
|
||||||
handleForwardResponseTrailer(w, md)
|
handleForwardResponseTrailer(w, mux, md)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ func FieldMaskFromRequestBody(r io.Reader, msg proto.Message) (*field_mask.Field
|
||||||
var root interface{}
|
var root interface{}
|
||||||
|
|
||||||
if err := json.NewDecoder(r).Decode(&root); err != nil {
|
if err := json.NewDecoder(r).Decode(&root); err != nil {
|
||||||
if err == io.EOF {
|
if errors.Is(err, io.EOF) {
|
||||||
return fm, nil
|
return fm, nil
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -41,7 +41,7 @@ func FieldMaskFromRequestBody(r io.Reader, msg proto.Message) (*field_mask.Field
|
||||||
|
|
||||||
m, ok := item.node.(map[string]interface{})
|
m, ok := item.node.(map[string]interface{})
|
||||||
switch {
|
switch {
|
||||||
case ok:
|
case ok && len(m) > 0:
|
||||||
// if the item is an object, then enqueue all of its children
|
// if the item is an object, then enqueue all of its children
|
||||||
for k, v := range m {
|
for k, v := range m {
|
||||||
if item.msg == nil {
|
if item.msg == nil {
|
||||||
|
@ -96,6 +96,8 @@ func FieldMaskFromRequestBody(r io.Reader, msg proto.Message) (*field_mask.Field
|
||||||
queue = append(queue, child)
|
queue = append(queue, child)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case ok && len(m) == 0:
|
||||||
|
fallthrough
|
||||||
case len(item.path) > 0:
|
case len(item.path) > 0:
|
||||||
// otherwise, it's a leaf node so print its path
|
// otherwise, it's a leaf node so print its path
|
||||||
fm.Paths = append(fm.Paths, item.path)
|
fm.Paths = append(fm.Paths, item.path)
|
||||||
|
|
|
@ -2,10 +2,11 @@ package runtime
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/textproto"
|
"net/textproto"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"google.golang.org/genproto/googleapis/api/httpbody"
|
"google.golang.org/genproto/googleapis/api/httpbody"
|
||||||
|
@ -17,16 +18,10 @@ import (
|
||||||
|
|
||||||
// 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, mux *ServeMux, 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)
|
rc := http.NewResponseController(w)
|
||||||
if !ok {
|
|
||||||
grpclog.Infof("Flush not supported in %T", w)
|
|
||||||
http.Error(w, "unexpected type of web server", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
md, ok := ServerMetadataFromContext(ctx)
|
md, ok := ServerMetadataFromContext(ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
grpclog.Infof("Failed to extract ServerMetadata from context")
|
grpclog.Error("Failed to extract ServerMetadata from context")
|
||||||
http.Error(w, "unexpected error", http.StatusInternalServerError)
|
http.Error(w, "unexpected error", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -48,7 +43,7 @@ func ForwardResponseStream(ctx context.Context, mux *ServeMux, marshaler Marshal
|
||||||
var wroteHeader bool
|
var wroteHeader bool
|
||||||
for {
|
for {
|
||||||
resp, err := recv()
|
resp, err := recv()
|
||||||
if err == io.EOF {
|
if errors.Is(err, io.EOF) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -81,20 +76,29 @@ func ForwardResponseStream(ctx context.Context, mux *ServeMux, marshaler Marshal
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
grpclog.Infof("Failed to marshal response chunk: %v", err)
|
grpclog.Errorf("Failed to marshal response chunk: %v", err)
|
||||||
handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err, delimiter)
|
handleForwardResponseStreamError(ctx, wroteHeader, marshaler, w, req, mux, err, delimiter)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err := w.Write(buf); err != nil {
|
if _, err := w.Write(buf); err != nil {
|
||||||
grpclog.Infof("Failed to send response chunk: %v", err)
|
grpclog.Errorf("Failed to send response chunk: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
wroteHeader = true
|
wroteHeader = true
|
||||||
if _, err := w.Write(delimiter); err != nil {
|
if _, err := w.Write(delimiter); err != nil {
|
||||||
grpclog.Infof("Failed to send delimiter chunk: %v", err)
|
grpclog.Errorf("Failed to send delimiter chunk: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = rc.Flush()
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, http.ErrNotSupported) {
|
||||||
|
grpclog.Errorf("Flush not supported in %T", w)
|
||||||
|
http.Error(w, "unexpected type of web server", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
grpclog.Errorf("Failed to flush response to client: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
f.Flush()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,18 +112,20 @@ func handleForwardResponseServerMetadata(w http.ResponseWriter, mux *ServeMux, m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleForwardResponseTrailerHeader(w http.ResponseWriter, md ServerMetadata) {
|
func handleForwardResponseTrailerHeader(w http.ResponseWriter, mux *ServeMux, md ServerMetadata) {
|
||||||
for k := range md.TrailerMD {
|
for k := range md.TrailerMD {
|
||||||
tKey := textproto.CanonicalMIMEHeaderKey(fmt.Sprintf("%s%s", MetadataTrailerPrefix, k))
|
if h, ok := mux.outgoingTrailerMatcher(k); ok {
|
||||||
w.Header().Add("Trailer", tKey)
|
w.Header().Add("Trailer", textproto.CanonicalMIMEHeaderKey(h))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleForwardResponseTrailer(w http.ResponseWriter, md ServerMetadata) {
|
func handleForwardResponseTrailer(w http.ResponseWriter, mux *ServeMux, md ServerMetadata) {
|
||||||
for k, vs := range md.TrailerMD {
|
for k, vs := range md.TrailerMD {
|
||||||
tKey := fmt.Sprintf("%s%s", MetadataTrailerPrefix, k)
|
if h, ok := mux.outgoingTrailerMatcher(k); ok {
|
||||||
for _, v := range vs {
|
for _, v := range vs {
|
||||||
w.Header().Add(tKey, v)
|
w.Header().Add(h, v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,7 +140,7 @@ type responseBody interface {
|
||||||
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) {
|
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.Infof("Failed to extract ServerMetadata from context")
|
grpclog.Error("Failed to extract ServerMetadata from context")
|
||||||
}
|
}
|
||||||
|
|
||||||
handleForwardResponseServerMetadata(w, mux, md)
|
handleForwardResponseServerMetadata(w, mux, md)
|
||||||
|
@ -147,12 +153,10 @@ func ForwardResponseMessage(ctx context.Context, mux *ServeMux, marshaler Marsha
|
||||||
doForwardTrailers := requestAcceptsTrailers(req)
|
doForwardTrailers := requestAcceptsTrailers(req)
|
||||||
|
|
||||||
if doForwardTrailers {
|
if doForwardTrailers {
|
||||||
handleForwardResponseTrailerHeader(w, md)
|
handleForwardResponseTrailerHeader(w, mux, md)
|
||||||
w.Header().Set("Transfer-Encoding", "chunked")
|
w.Header().Set("Transfer-Encoding", "chunked")
|
||||||
}
|
}
|
||||||
|
|
||||||
handleForwardResponseTrailerHeader(w, md)
|
|
||||||
|
|
||||||
contentType := marshaler.ContentType(resp)
|
contentType := marshaler.ContentType(resp)
|
||||||
w.Header().Set("Content-Type", contentType)
|
w.Header().Set("Content-Type", contentType)
|
||||||
|
|
||||||
|
@ -168,17 +172,21 @@ func ForwardResponseMessage(ctx context.Context, mux *ServeMux, marshaler Marsha
|
||||||
buf, err = marshaler.Marshal(resp)
|
buf, err = marshaler.Marshal(resp)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
grpclog.Infof("Marshal error: %v", err)
|
grpclog.Errorf("Marshal error: %v", err)
|
||||||
HTTPError(ctx, mux, marshaler, w, req, err)
|
HTTPError(ctx, mux, marshaler, w, req, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !doForwardTrailers {
|
||||||
|
w.Header().Set("Content-Length", strconv.Itoa(len(buf)))
|
||||||
|
}
|
||||||
|
|
||||||
if _, err = w.Write(buf); err != nil {
|
if _, err = w.Write(buf); err != nil {
|
||||||
grpclog.Infof("Failed to write response: %v", err)
|
grpclog.Errorf("Failed to write response: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if doForwardTrailers {
|
if doForwardTrailers {
|
||||||
handleForwardResponseTrailer(w, md)
|
handleForwardResponseTrailer(w, mux, md)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +201,7 @@ func handleForwardResponseOptions(ctx context.Context, w http.ResponseWriter, re
|
||||||
}
|
}
|
||||||
for _, opt := range opts {
|
for _, opt := range opts {
|
||||||
if err := opt(ctx, w, resp); err != nil {
|
if err := opt(ctx, w, resp); err != nil {
|
||||||
grpclog.Infof("Error handling ForwardResponseOptions: %v", err)
|
grpclog.Errorf("Error handling ForwardResponseOptions: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,15 +217,15 @@ func handleForwardResponseStreamError(ctx context.Context, wroteHeader bool, mar
|
||||||
}
|
}
|
||||||
buf, err := marshaler.Marshal(msg)
|
buf, err := marshaler.Marshal(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
grpclog.Infof("Failed to marshal an error: %v", err)
|
grpclog.Errorf("Failed to marshal an error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err := w.Write(buf); err != nil {
|
if _, err := w.Write(buf); err != nil {
|
||||||
grpclog.Infof("Failed to notify error to client: %v", err)
|
grpclog.Errorf("Failed to notify error to client: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err := w.Write(delimiter); err != nil {
|
if _, err := w.Write(delimiter); err != nil {
|
||||||
grpclog.Infof("Failed to send delimiter chunk: %v", err)
|
grpclog.Errorf("Failed to send delimiter chunk: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_httpbodyproto.go
generated
vendored
2
vendor/github.com/grpc-ecosystem/grpc-gateway/v2/runtime/marshal_httpbodyproto.go
generated
vendored
|
@ -26,7 +26,7 @@ func (h *HTTPBodyMarshaler) ContentType(v interface{}) string {
|
||||||
// google.api.HttpBody message, otherwise it falls back to the default Marshaler.
|
// google.api.HttpBody message, otherwise it falls back to the default Marshaler.
|
||||||
func (h *HTTPBodyMarshaler) Marshal(v interface{}) ([]byte, error) {
|
func (h *HTTPBodyMarshaler) Marshal(v interface{}) ([]byte, error) {
|
||||||
if httpBody, ok := v.(*httpbody.HttpBody); ok {
|
if httpBody, ok := v.(*httpbody.HttpBody); ok {
|
||||||
return httpBody.Data, nil
|
return httpBody.GetData(), nil
|
||||||
}
|
}
|
||||||
return h.Marshaler.Marshal(v)
|
return h.Marshaler.Marshal(v)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,11 @@ func (j *JSONBuiltin) Marshal(v interface{}) ([]byte, error) {
|
||||||
return json.Marshal(v)
|
return json.Marshal(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MarshalIndent is like Marshal but applies Indent to format the output
|
||||||
|
func (j *JSONBuiltin) MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
|
||||||
|
return json.MarshalIndent(v, prefix, indent)
|
||||||
|
}
|
||||||
|
|
||||||
// Unmarshal unmarshals JSON data into "v".
|
// Unmarshal unmarshals JSON data into "v".
|
||||||
func (j *JSONBuiltin) Unmarshal(data []byte, v interface{}) error {
|
func (j *JSONBuiltin) Unmarshal(data []byte, v interface{}) error {
|
||||||
return json.Unmarshal(data, v)
|
return json.Unmarshal(data, v)
|
||||||
|
|
|
@ -30,10 +30,6 @@ func (*JSONPb) ContentType(_ interface{}) string {
|
||||||
|
|
||||||
// Marshal marshals "v" into JSON.
|
// Marshal marshals "v" into JSON.
|
||||||
func (j *JSONPb) Marshal(v interface{}) ([]byte, error) {
|
func (j *JSONPb) Marshal(v interface{}) ([]byte, error) {
|
||||||
if _, ok := v.(proto.Message); !ok {
|
|
||||||
return j.marshalNonProtoField(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
if err := j.marshalTo(&buf, v); err != nil {
|
if err := j.marshalTo(&buf, v); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -48,9 +44,17 @@ func (j *JSONPb) marshalTo(w io.Writer, v interface{}) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if j.Indent != "" {
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
if err := json.Indent(b, buf, "", j.Indent); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
buf = b.Bytes()
|
||||||
|
}
|
||||||
_, err = w.Write(buf)
|
_, err = w.Write(buf)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := j.MarshalOptions.Marshal(p)
|
b, err := j.MarshalOptions.Marshal(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -150,9 +154,6 @@ func (j *JSONPb) marshalNonProtoField(v interface{}) ([]byte, error) {
|
||||||
}
|
}
|
||||||
m[fmt.Sprintf("%v", k.Interface())] = (*json.RawMessage)(&buf)
|
m[fmt.Sprintf("%v", k.Interface())] = (*json.RawMessage)(&buf)
|
||||||
}
|
}
|
||||||
if j.Indent != "" {
|
|
||||||
return json.MarshalIndent(m, "", j.Indent)
|
|
||||||
}
|
|
||||||
return json.Marshal(m)
|
return json.Marshal(m)
|
||||||
}
|
}
|
||||||
if enum, ok := rv.Interface().(protoEnum); ok && !j.UseEnumNumbers {
|
if enum, ok := rv.Interface().(protoEnum); ok && !j.UseEnumNumbers {
|
||||||
|
|
|
@ -46,7 +46,7 @@ func MarshalerForRequest(mux *ServeMux, r *http.Request) (inbound Marshaler, out
|
||||||
for _, contentTypeVal := range r.Header[contentTypeHeader] {
|
for _, contentTypeVal := range r.Header[contentTypeHeader] {
|
||||||
contentType, _, err := mime.ParseMediaType(contentTypeVal)
|
contentType, _, err := mime.ParseMediaType(contentTypeVal)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
grpclog.Infof("Failed to parse Content-Type %s: %v", contentTypeVal, err)
|
grpclog.Errorf("Failed to parse Content-Type %s: %v", contentTypeVal, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if m, ok := mux.marshalers.mimeMap[contentType]; ok {
|
if m, ok := mux.marshalers.mimeMap[contentType]; ok {
|
||||||
|
|
|
@ -57,6 +57,7 @@ type ServeMux struct {
|
||||||
marshalers marshalerRegistry
|
marshalers marshalerRegistry
|
||||||
incomingHeaderMatcher HeaderMatcherFunc
|
incomingHeaderMatcher HeaderMatcherFunc
|
||||||
outgoingHeaderMatcher HeaderMatcherFunc
|
outgoingHeaderMatcher HeaderMatcherFunc
|
||||||
|
outgoingTrailerMatcher HeaderMatcherFunc
|
||||||
metadataAnnotators []func(context.Context, *http.Request) metadata.MD
|
metadataAnnotators []func(context.Context, *http.Request) metadata.MD
|
||||||
errorHandler ErrorHandlerFunc
|
errorHandler ErrorHandlerFunc
|
||||||
streamErrorHandler StreamErrorHandlerFunc
|
streamErrorHandler StreamErrorHandlerFunc
|
||||||
|
@ -114,10 +115,18 @@ func DefaultHeaderMatcher(key string) (string, bool) {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func defaultOutgoingHeaderMatcher(key string) (string, bool) {
|
||||||
|
return fmt.Sprintf("%s%s", MetadataHeaderPrefix, key), true
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultOutgoingTrailerMatcher(key string) (string, bool) {
|
||||||
|
return fmt.Sprintf("%s%s", MetadataTrailerPrefix, key), true
|
||||||
|
}
|
||||||
|
|
||||||
// WithIncomingHeaderMatcher returns a ServeMuxOption representing a headerMatcher for incoming request to gateway.
|
// 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
|
// 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.
|
// passed to gRPC context. To transform the header before passing to gRPC context, matcher should return the modified header.
|
||||||
func WithIncomingHeaderMatcher(fn HeaderMatcherFunc) ServeMuxOption {
|
func WithIncomingHeaderMatcher(fn HeaderMatcherFunc) ServeMuxOption {
|
||||||
for _, header := range fn.matchedMalformedHeaders() {
|
for _, header := range fn.matchedMalformedHeaders() {
|
||||||
grpclog.Warningf("The configured forwarding filter would allow %q to be sent to the gRPC server, which will likely cause errors. See https://github.com/grpc/grpc-go/pull/4803#issuecomment-986093310 for more information.", header)
|
grpclog.Warningf("The configured forwarding filter would allow %q to be sent to the gRPC server, which will likely cause errors. See https://github.com/grpc/grpc-go/pull/4803#issuecomment-986093310 for more information.", header)
|
||||||
|
@ -147,13 +156,24 @@ func (fn HeaderMatcherFunc) matchedMalformedHeaders() []string {
|
||||||
//
|
//
|
||||||
// This matcher will be called with each header in response header metadata. If matcher returns true, that header will be
|
// 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,
|
// passed to http response returned from gateway. To transform the header before passing to response,
|
||||||
// matcher should return modified header.
|
// matcher should return the modified header.
|
||||||
func WithOutgoingHeaderMatcher(fn HeaderMatcherFunc) ServeMuxOption {
|
func WithOutgoingHeaderMatcher(fn HeaderMatcherFunc) ServeMuxOption {
|
||||||
return func(mux *ServeMux) {
|
return func(mux *ServeMux) {
|
||||||
mux.outgoingHeaderMatcher = fn
|
mux.outgoingHeaderMatcher = fn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithOutgoingTrailerMatcher returns a ServeMuxOption representing a headerMatcher for outgoing response from gateway.
|
||||||
|
//
|
||||||
|
// This matcher will be called with each header in response trailer 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 the modified header.
|
||||||
|
func WithOutgoingTrailerMatcher(fn HeaderMatcherFunc) ServeMuxOption {
|
||||||
|
return func(mux *ServeMux) {
|
||||||
|
mux.outgoingTrailerMatcher = fn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithMetadata returns a ServeMuxOption for passing metadata to a gRPC context.
|
// 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
|
// This can be used by services that need to read from http.Request and modify gRPC context. A common use case
|
||||||
|
@ -273,11 +293,11 @@ func NewServeMux(opts ...ServeMuxOption) *ServeMux {
|
||||||
if serveMux.incomingHeaderMatcher == nil {
|
if serveMux.incomingHeaderMatcher == nil {
|
||||||
serveMux.incomingHeaderMatcher = DefaultHeaderMatcher
|
serveMux.incomingHeaderMatcher = DefaultHeaderMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
if serveMux.outgoingHeaderMatcher == nil {
|
if serveMux.outgoingHeaderMatcher == nil {
|
||||||
serveMux.outgoingHeaderMatcher = func(key string) (string, bool) {
|
serveMux.outgoingHeaderMatcher = defaultOutgoingHeaderMatcher
|
||||||
return fmt.Sprintf("%s%s", MetadataHeaderPrefix, key), true
|
}
|
||||||
}
|
if serveMux.outgoingTrailerMatcher == nil {
|
||||||
|
serveMux.outgoingTrailerMatcher = defaultOutgoingTrailerMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
return serveMux
|
return serveMux
|
||||||
|
@ -321,13 +341,13 @@ func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if override := r.Header.Get("X-HTTP-Method-Override"); override != "" && s.isPathLengthFallback(r) {
|
if override := r.Header.Get("X-HTTP-Method-Override"); override != "" && s.isPathLengthFallback(r) {
|
||||||
r.Method = strings.ToUpper(override)
|
|
||||||
if err := r.ParseForm(); err != nil {
|
if err := r.ParseForm(); err != nil {
|
||||||
_, outboundMarshaler := MarshalerForRequest(s, r)
|
_, outboundMarshaler := MarshalerForRequest(s, r)
|
||||||
sterr := status.Error(codes.InvalidArgument, err.Error())
|
sterr := status.Error(codes.InvalidArgument, err.Error())
|
||||||
s.errorHandler(ctx, s, outboundMarshaler, w, r, sterr)
|
s.errorHandler(ctx, s, outboundMarshaler, w, r, sterr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
r.Method = strings.ToUpper(override)
|
||||||
}
|
}
|
||||||
|
|
||||||
var pathComponents []string
|
var pathComponents []string
|
||||||
|
|
|
@ -52,13 +52,13 @@ type Pattern struct {
|
||||||
// It returns an error if the given definition is invalid.
|
// It returns an error if the given definition is invalid.
|
||||||
func NewPattern(version int, ops []int, pool []string, verb string) (Pattern, error) {
|
func NewPattern(version int, ops []int, pool []string, verb string) (Pattern, error) {
|
||||||
if version != 1 {
|
if version != 1 {
|
||||||
grpclog.Infof("unsupported version: %d", version)
|
grpclog.Errorf("unsupported version: %d", version)
|
||||||
return Pattern{}, ErrInvalidPattern
|
return Pattern{}, ErrInvalidPattern
|
||||||
}
|
}
|
||||||
|
|
||||||
l := len(ops)
|
l := len(ops)
|
||||||
if l%2 != 0 {
|
if l%2 != 0 {
|
||||||
grpclog.Infof("odd number of ops codes: %d", l)
|
grpclog.Errorf("odd number of ops codes: %d", l)
|
||||||
return Pattern{}, ErrInvalidPattern
|
return Pattern{}, ErrInvalidPattern
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,14 +81,14 @@ func NewPattern(version int, ops []int, pool []string, verb string) (Pattern, er
|
||||||
stack++
|
stack++
|
||||||
case utilities.OpPushM:
|
case utilities.OpPushM:
|
||||||
if pushMSeen {
|
if pushMSeen {
|
||||||
grpclog.Infof("pushM appears twice")
|
grpclog.Error("pushM appears twice")
|
||||||
return Pattern{}, ErrInvalidPattern
|
return Pattern{}, ErrInvalidPattern
|
||||||
}
|
}
|
||||||
pushMSeen = true
|
pushMSeen = true
|
||||||
stack++
|
stack++
|
||||||
case utilities.OpLitPush:
|
case utilities.OpLitPush:
|
||||||
if op.operand < 0 || len(pool) <= op.operand {
|
if op.operand < 0 || len(pool) <= op.operand {
|
||||||
grpclog.Infof("negative literal index: %d", op.operand)
|
grpclog.Errorf("negative literal index: %d", op.operand)
|
||||||
return Pattern{}, ErrInvalidPattern
|
return Pattern{}, ErrInvalidPattern
|
||||||
}
|
}
|
||||||
if pushMSeen {
|
if pushMSeen {
|
||||||
|
@ -97,18 +97,18 @@ func NewPattern(version int, ops []int, pool []string, verb string) (Pattern, er
|
||||||
stack++
|
stack++
|
||||||
case utilities.OpConcatN:
|
case utilities.OpConcatN:
|
||||||
if op.operand <= 0 {
|
if op.operand <= 0 {
|
||||||
grpclog.Infof("negative concat size: %d", op.operand)
|
grpclog.Errorf("negative concat size: %d", op.operand)
|
||||||
return Pattern{}, ErrInvalidPattern
|
return Pattern{}, ErrInvalidPattern
|
||||||
}
|
}
|
||||||
stack -= op.operand
|
stack -= op.operand
|
||||||
if stack < 0 {
|
if stack < 0 {
|
||||||
grpclog.Info("stack underflow")
|
grpclog.Error("stack underflow")
|
||||||
return Pattern{}, ErrInvalidPattern
|
return Pattern{}, ErrInvalidPattern
|
||||||
}
|
}
|
||||||
stack++
|
stack++
|
||||||
case utilities.OpCapture:
|
case utilities.OpCapture:
|
||||||
if op.operand < 0 || len(pool) <= op.operand {
|
if op.operand < 0 || len(pool) <= op.operand {
|
||||||
grpclog.Infof("variable name index out of bound: %d", op.operand)
|
grpclog.Errorf("variable name index out of bound: %d", op.operand)
|
||||||
return Pattern{}, ErrInvalidPattern
|
return Pattern{}, ErrInvalidPattern
|
||||||
}
|
}
|
||||||
v := pool[op.operand]
|
v := pool[op.operand]
|
||||||
|
@ -116,11 +116,11 @@ func NewPattern(version int, ops []int, pool []string, verb string) (Pattern, er
|
||||||
vars = append(vars, v)
|
vars = append(vars, v)
|
||||||
stack--
|
stack--
|
||||||
if stack < 0 {
|
if stack < 0 {
|
||||||
grpclog.Infof("stack underflow")
|
grpclog.Error("stack underflow")
|
||||||
return Pattern{}, ErrInvalidPattern
|
return Pattern{}, ErrInvalidPattern
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
grpclog.Infof("invalid opcode: %d", op.code)
|
grpclog.Errorf("invalid opcode: %d", op.code)
|
||||||
return Pattern{}, ErrInvalidPattern
|
return Pattern{}, ErrInvalidPattern
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,11 +51,13 @@ func (*DefaultQueryParser) Parse(msg proto.Message, values url.Values, filter *u
|
||||||
key = match[1]
|
key = match[1]
|
||||||
values = append([]string{match[2]}, values...)
|
values = append([]string{match[2]}, values...)
|
||||||
}
|
}
|
||||||
fieldPath := strings.Split(key, ".")
|
|
||||||
|
msgValue := msg.ProtoReflect()
|
||||||
|
fieldPath := normalizeFieldPath(msgValue, strings.Split(key, "."))
|
||||||
if filter.HasCommonPrefix(fieldPath) {
|
if filter.HasCommonPrefix(fieldPath) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := populateFieldValueFromPath(msg.ProtoReflect(), fieldPath, values); err != nil {
|
if err := populateFieldValueFromPath(msgValue, fieldPath, values); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,6 +70,38 @@ func PopulateFieldFromPath(msg proto.Message, fieldPathString string, value stri
|
||||||
return populateFieldValueFromPath(msg.ProtoReflect(), fieldPath, []string{value})
|
return populateFieldValueFromPath(msg.ProtoReflect(), fieldPath, []string{value})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func normalizeFieldPath(msgValue protoreflect.Message, fieldPath []string) []string {
|
||||||
|
newFieldPath := make([]string, 0, len(fieldPath))
|
||||||
|
for i, fieldName := range fieldPath {
|
||||||
|
fields := msgValue.Descriptor().Fields()
|
||||||
|
fieldDesc := fields.ByTextName(fieldName)
|
||||||
|
if fieldDesc == nil {
|
||||||
|
fieldDesc = fields.ByJSONName(fieldName)
|
||||||
|
}
|
||||||
|
if fieldDesc == nil {
|
||||||
|
// return initial field path values if no matching message field was found
|
||||||
|
return fieldPath
|
||||||
|
}
|
||||||
|
|
||||||
|
newFieldPath = append(newFieldPath, string(fieldDesc.Name()))
|
||||||
|
|
||||||
|
// If this is the last element, we're done
|
||||||
|
if i == len(fieldPath)-1 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only singular message fields are allowed
|
||||||
|
if fieldDesc.Message() == nil || fieldDesc.Cardinality() == protoreflect.Repeated {
|
||||||
|
return fieldPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the nested message
|
||||||
|
msgValue = msgValue.Get(fieldDesc).Message()
|
||||||
|
}
|
||||||
|
|
||||||
|
return newFieldPath
|
||||||
|
}
|
||||||
|
|
||||||
func populateFieldValueFromPath(msgValue protoreflect.Message, fieldPath []string, values []string) error {
|
func populateFieldValueFromPath(msgValue protoreflect.Message, fieldPath []string, values []string) error {
|
||||||
if len(fieldPath) < 1 {
|
if len(fieldPath) < 1 {
|
||||||
return errors.New("no field path")
|
return errors.New("no field path")
|
||||||
|
|
|
@ -164,8 +164,8 @@ github.com/google/shlex
|
||||||
# github.com/gorilla/mux v1.8.1
|
# github.com/gorilla/mux v1.8.1
|
||||||
## explicit; go 1.20
|
## explicit; go 1.20
|
||||||
github.com/gorilla/mux
|
github.com/gorilla/mux
|
||||||
# github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0
|
# github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0
|
||||||
## explicit; go 1.17
|
## explicit; go 1.20
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule
|
github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2/runtime
|
github.com/grpc-ecosystem/grpc-gateway/v2/runtime
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2/utilities
|
github.com/grpc-ecosystem/grpc-gateway/v2/utilities
|
||||||
|
|
Loading…
Reference in New Issue