Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
132278ec
Commit
132278ec
authored
Dec 13, 2017
by
Joe Betz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Version bump to grpc-gateway v1.3.0
parent
0abafb24
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
475 additions
and
64 deletions
+475
-64
Godeps.json
Godeps/Godeps.json
+6
-6
BUILD
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/BUILD
+2
-1
context.go
...github.com/grpc-ecosystem/grpc-gateway/runtime/context.go
+54
-10
errors.go
.../github.com/grpc-ecosystem/grpc-gateway/runtime/errors.go
+13
-7
handler.go
...github.com/grpc-ecosystem/grpc-gateway/runtime/handler.go
+20
-15
stream_chunk.pb.go
...cosystem/grpc-gateway/runtime/internal/stream_chunk.pb.go
+30
-3
mux.go
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/mux.go
+136
-8
pattern.go
...github.com/grpc-ecosystem/grpc-gateway/runtime/pattern.go
+1
-1
proto_errors.go
...b.com/grpc-ecosystem/grpc-gateway/runtime/proto_errors.go
+61
-0
query.go
...r/github.com/grpc-ecosystem/grpc-gateway/runtime/query.go
+152
-13
No files found.
Godeps/Godeps.json
View file @
132278ec
...
@@ -1871,18 +1871,18 @@
...
@@ -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"
:
"8
4398b94e188ee336f307779b57b3aa91af7063c
"
"Rev"
:
"8
cc3a55af3bcf171a1c23a90c4df9cf591706104
"
},
},
{
{
"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"
:
"8
4398b94e188ee336f307779b57b3aa91af7063c
"
"Rev"
:
"8
cc3a55af3bcf171a1c23a90c4df9cf591706104
"
},
},
{
{
"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"
:
"8
4398b94e188ee336f307779b57b3aa91af7063c
"
"Rev"
:
"8
cc3a55af3bcf171a1c23a90c4df9cf591706104
"
},
},
{
{
"ImportPath"
:
"github.com/hashicorp/golang-lru"
,
"ImportPath"
:
"github.com/hashicorp/golang-lru"
,
...
...
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/BUILD
View file @
132278ec
...
@@ -15,6 +15,7 @@ go_library(
...
@@ -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(
...
@@ -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",
],
],
)
)
...
...
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/context.go
View file @
132278ec
...
@@ -9,18 +9,23 @@ import (
...
@@ -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",
...
@@ -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
...
@@ -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) {
...
@@ -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
}
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/errors.go
View file @
132278ec
...
@@ -6,9 +6,9 @@ import (
...
@@ -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 (
...
@@ -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
int
32
`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() {}
...
@@ -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
,
m
ux
*
ServeMux
,
m
arshaler
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
:
int
32
(
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
...
@@ -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
,
m
ux
,
m
d
)
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
)
...
...
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/handler.go
View file @
132278ec
...
@@ -9,12 +9,13 @@ import (
...
@@ -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
,
m
ux
*
ServeMux
,
m
arshaler
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
...
@@ -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
,
m
ux
,
m
d
)
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
...
@@ -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
...
@@ -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
,
m
ux
*
ServeMux
,
m
d
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
...
@@ -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
,
v
s
[
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
,
m
ux
*
ServeMux
,
m
arshaler
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
,
m
ux
,
m
d
)
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
,
m
ux
,
m
arshaler
,
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
,
m
ux
,
m
arshaler
,
w
,
req
,
err
)
return
return
}
}
...
@@ -146,7 +148,10 @@ func handleForwardResponseStreamError(marshaler Marshaler, w http.ResponseWriter
...
@@ -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
{
...
...
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/internal/stream_chunk.pb.go
View file @
132278ec
// 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
...
@@ -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
...
@@ -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
,
0x0
9
,
0x6e
,
0x88
,
0x02
,
0xff
,
0x34
,
0x8e
,
0xbf
,
0xee
,
0x82
,
0x30
,
0x1f
,
0x8b
,
0x08
,
0x00
,
0x00
,
0x0
0
,
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
,
...
...
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/mux.go
View file @
132278ec
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 {
...
@@ -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.
...
@@ -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 {
...
@@ -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) {
...
@@ -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) {
...
@@ -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) {
...
@@ -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) {
...
@@ -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.
...
...
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/pattern.go
View file @
132278ec
...
@@ -21,7 +21,7 @@ type op struct {
...
@@ -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
...
...
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/proto_errors.go
0 → 100644
View file @
132278ec
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
)
}
vendor/github.com/grpc-ecosystem/grpc-gateway/runtime/query.go
View file @
132278ec
...
@@ -4,7 +4,9 @@ import (
...
@@ -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 []
...
@@ -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 []
...
@@ -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 {
...
@@ -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
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment