From 5b30033490faff3324834a88ed11d60f1c3f8be1 Mon Sep 17 00:00:00 2001 From: Doug Fawley Date: Thu, 7 Apr 2022 14:33:52 -0700 Subject: [PATCH 1/4] server: clarify documentation around setting and sending headers and ServerStream errors --- server.go | 38 ++++++++++++++++++++++++++++++-------- stream.go | 6 ++++-- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/server.go b/server.go index 96431a058bf..5fc7e54ad07 100644 --- a/server.go +++ b/server.go @@ -1801,12 +1801,26 @@ func (s *Server) getCodec(contentSubtype string) baseCodec { return codec } -// SetHeader sets the header metadata. -// When called multiple times, all the provided metadata will be merged. -// All the metadata will be sent out when one of the following happens: -// - grpc.SendHeader() is called; -// - The first response is sent out; -// - An RPC status is sent out (error or success). +// SetHeader sets the header metadata to be sent from the server to the client. +// The context provided must be the context passed to the server's handler. +// +// Streaming RPCs should prefer the SetHeader method of the ServerStream. +// +// When called multiple times, all the provided metadata will be merged. All +// the metadata will be sent out when one of the following happens: +// +// - grpc.SendHeader is called, or for streaming handlers, stream.SendHeader. +// - The first response message is sent. For unary handlers, this occurs when +// the handler returns; for streaming handlers, this can happen when stream's +// SendMsg method is called. +// - An RPC status is sent out (error or success). This occurs when the handler +// returns. +// +// SetHeader will fail if called after any of these events. +// +// The error returned is compatible with the status package. However, the +// status will often not match the status seen by the client application, and +// therefore, should not be relied upon for this purpose. func SetHeader(ctx context.Context, md metadata.MD) error { if md.Len() == 0 { return nil @@ -1818,8 +1832,12 @@ func SetHeader(ctx context.Context, md metadata.MD) error { return stream.SetHeader(md) } -// SendHeader sends header metadata. It may be called at most once. -// The provided md and headers set by SetHeader() will be sent. +// SendHeader sends header metadata. It may be called at most once. The +// provided md and headers set by SetHeader() will be sent. +// +// The error returned is compatible with the status package. However, the +// status will often not match the status seen by the client application, and +// therefore, should not be relied upon for this purpose. func SendHeader(ctx context.Context, md metadata.MD) error { stream := ServerTransportStreamFromContext(ctx) if stream == nil { @@ -1833,6 +1851,10 @@ func SendHeader(ctx context.Context, md metadata.MD) error { // SetTrailer sets the trailer metadata that will be sent when an RPC returns. // When called more than once, all the provided metadata will be merged. +// +// The error returned is compatible with the status package. However, the +// status will often not match the status seen by the client application, and +// therefore, should not be relied upon for this purpose. func SetTrailer(ctx context.Context, md metadata.MD) error { if md.Len() == 0 { return nil diff --git a/stream.go b/stream.go index e0b30b46fb1..aba044ec930 100644 --- a/stream.go +++ b/stream.go @@ -1370,8 +1370,10 @@ func (as *addrConnStream) finish(err error) { // ServerStream defines the server-side behavior of a streaming RPC. // -// All errors returned from ServerStream methods are compatible with the -// status package. +// Errors returned from ServerStream methods are compatible with the status +// package. However, the status will often not match the status seen by the +// client application, and therefore, should not be relied upon for this +// purpose. type ServerStream interface { // SetHeader sets the header metadata. It may be called multiple times. // When call multiple times, all the provided metadata will be merged. From ab5679cb7a92baf8efdc4ec5aa91f88740f3f737 Mon Sep 17 00:00:00 2001 From: Doug Fawley Date: Fri, 8 Apr 2022 11:38:04 -0700 Subject: [PATCH 2/4] updates --- server.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server.go b/server.go index 5fc7e54ad07..5cbca9ea2d1 100644 --- a/server.go +++ b/server.go @@ -1816,11 +1816,11 @@ func (s *Server) getCodec(contentSubtype string) baseCodec { // - An RPC status is sent out (error or success). This occurs when the handler // returns. // -// SetHeader will fail if called after any of these events. +// SetHeader will fail if called after any of the events above. // // The error returned is compatible with the status package. However, the -// status will often not match the status seen by the client application, and -// therefore, should not be relied upon for this purpose. +// status code will often not match the RPC status as seen by the client +// application, and therefore, should not be relied upon for this purpose. func SetHeader(ctx context.Context, md metadata.MD) error { if md.Len() == 0 { return nil From c5af1cd8b84e57759cad22859a1391db18000cc9 Mon Sep 17 00:00:00 2001 From: Doug Fawley Date: Fri, 8 Apr 2022 11:53:18 -0700 Subject: [PATCH 3/4] finish updates --- server.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/server.go b/server.go index 5cbca9ea2d1..65de84b3007 100644 --- a/server.go +++ b/server.go @@ -1832,12 +1832,14 @@ func SetHeader(ctx context.Context, md metadata.MD) error { return stream.SetHeader(md) } -// SendHeader sends header metadata. It may be called at most once. The -// provided md and headers set by SetHeader() will be sent. +// SendHeader sends header metadata. It may be called at most once, and may not +// be called after any event that causes headers to be sent (see SetHeader for +// a complete list). The provided md and headers set by SetHeader() will be +// sent. // // The error returned is compatible with the status package. However, the -// status will often not match the status seen by the client application, and -// therefore, should not be relied upon for this purpose. +// status code will often not match the RPC status as seen by the client +// application, and therefore, should not be relied upon for this purpose. func SendHeader(ctx context.Context, md metadata.MD) error { stream := ServerTransportStreamFromContext(ctx) if stream == nil { @@ -1853,8 +1855,8 @@ func SendHeader(ctx context.Context, md metadata.MD) error { // When called more than once, all the provided metadata will be merged. // // The error returned is compatible with the status package. However, the -// status will often not match the status seen by the client application, and -// therefore, should not be relied upon for this purpose. +// status code will often not match the RPC status as seen by the client +// application, and therefore, should not be relied upon for this purpose. func SetTrailer(ctx context.Context, md metadata.MD) error { if md.Len() == 0 { return nil From c67012d1e36ea3b7673c3e24425daa7486971bb8 Mon Sep 17 00:00:00 2001 From: Doug Fawley Date: Fri, 8 Apr 2022 11:58:09 -0700 Subject: [PATCH 4/4] finish the finished updates --- stream.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stream.go b/stream.go index aba044ec930..c72aac5877c 100644 --- a/stream.go +++ b/stream.go @@ -1371,9 +1371,9 @@ func (as *addrConnStream) finish(err error) { // ServerStream defines the server-side behavior of a streaming RPC. // // Errors returned from ServerStream methods are compatible with the status -// package. However, the status will often not match the status seen by the -// client application, and therefore, should not be relied upon for this -// purpose. +// package. However, the status code will often not match the RPC status as +// seen by the client application, and therefore, should not be relied upon for +// this purpose. type ServerStream interface { // SetHeader sets the header metadata. It may be called multiple times. // When call multiple times, all the provided metadata will be merged.