| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | /* | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright 2017 gRPC authors. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Package status implements errors returned by gRPC.  These errors are | 
					
						
							|  |  |  | // serialized and transmitted on the wire between server and client, and allow | 
					
						
							|  |  |  | // for additional data to be transmitted via the Details field in the status | 
					
						
							|  |  |  | // proto.  gRPC service handlers should return an error created by this | 
					
						
							|  |  |  | // package, and gRPC clients should expect a corresponding error to be | 
					
						
							|  |  |  | // returned from the RPC call. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // This package upholds the invariants that a non-nil error may not | 
					
						
							|  |  |  | // contain an OK code, and an OK code must result in a nil error. | 
					
						
							|  |  |  | package status | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	spb "google.golang.org/genproto/googleapis/rpc/status" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"google.golang.org/grpc/codes" | 
					
						
							|  |  |  | 	"google.golang.org/grpc/internal/status" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Status references google.golang.org/grpc/internal/status. It represents an | 
					
						
							|  |  |  | // RPC status code, message, and details.  It is immutable and should be | 
					
						
							|  |  |  | // created with New, Newf, or FromProto. | 
					
						
							|  |  |  | // https://godoc.org/google.golang.org/grpc/internal/status | 
					
						
							|  |  |  | type Status = status.Status | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // New returns a Status representing c and msg. | 
					
						
							|  |  |  | func New(c codes.Code, msg string) *Status { | 
					
						
							|  |  |  | 	return status.New(c, msg) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Newf returns New(c, fmt.Sprintf(format, a...)). | 
					
						
							|  |  |  | func Newf(c codes.Code, format string, a ...interface{}) *Status { | 
					
						
							|  |  |  | 	return New(c, fmt.Sprintf(format, a...)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Error returns an error representing c and msg.  If c is OK, returns nil. | 
					
						
							|  |  |  | func Error(c codes.Code, msg string) error { | 
					
						
							|  |  |  | 	return New(c, msg).Err() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Errorf returns Error(c, fmt.Sprintf(format, a...)). | 
					
						
							|  |  |  | func Errorf(c codes.Code, format string, a ...interface{}) error { | 
					
						
							|  |  |  | 	return Error(c, fmt.Sprintf(format, a...)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ErrorProto returns an error representing s.  If s.Code is OK, returns nil. | 
					
						
							|  |  |  | func ErrorProto(s *spb.Status) error { | 
					
						
							|  |  |  | 	return FromProto(s).Err() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // FromProto returns a Status representing s. | 
					
						
							|  |  |  | func FromProto(s *spb.Status) *Status { | 
					
						
							|  |  |  | 	return status.FromProto(s) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // FromError returns a Status representation of err. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //   - If err was produced by this package or implements the method `GRPCStatus() | 
					
						
							| 
									
										
										
										
											2023-06-05 10:15:05 +02:00
										 |  |  | //     *Status`, or if err wraps a type satisfying this, the appropriate Status is | 
					
						
							|  |  |  | //     returned.  For wrapped errors, the message returned contains the entire | 
					
						
							|  |  |  | //     err.Error() text and not just the wrapped status. | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | // | 
					
						
							|  |  |  | //   - If err is nil, a Status is returned with codes.OK and no message. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //   - Otherwise, err is an error not compatible with this package.  In this | 
					
						
							|  |  |  | //     case, a Status is returned with codes.Unknown and err's Error() message, | 
					
						
							|  |  |  | //     and ok is false. | 
					
						
							|  |  |  | func FromError(err error) (s *Status, ok bool) { | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		return nil, true | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-06-05 10:15:05 +02:00
										 |  |  | 	type grpcstatus interface{ GRPCStatus() *Status } | 
					
						
							|  |  |  | 	if gs, ok := err.(grpcstatus); ok { | 
					
						
							|  |  |  | 		return gs.GRPCStatus(), true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var gs grpcstatus | 
					
						
							|  |  |  | 	if errors.As(err, &gs) { | 
					
						
							|  |  |  | 		p := gs.GRPCStatus().Proto() | 
					
						
							|  |  |  | 		p.Message = err.Error() | 
					
						
							|  |  |  | 		return status.FromProto(p), true | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return New(codes.Unknown, err.Error()), false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Convert is a convenience function which removes the need to handle the | 
					
						
							|  |  |  | // boolean return value from FromError. | 
					
						
							|  |  |  | func Convert(err error) *Status { | 
					
						
							|  |  |  | 	s, _ := FromError(err) | 
					
						
							|  |  |  | 	return s | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-05 10:15:05 +02:00
										 |  |  | // Code returns the Code of the error if it is a Status error or if it wraps a | 
					
						
							|  |  |  | // Status error. If that is not the case, it returns codes.OK if err is nil, or | 
					
						
							|  |  |  | // codes.Unknown otherwise. | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | func Code(err error) codes.Code { | 
					
						
							|  |  |  | 	// Don't use FromError to avoid allocation of OK status. | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		return codes.OK | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-06-05 10:15:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return Convert(err).Code() | 
					
						
							| 
									
										
										
										
											2023-05-09 19:19:48 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // FromContextError converts a context error or wrapped context error into a | 
					
						
							|  |  |  | // Status.  It returns a Status with codes.OK if err is nil, or a Status with | 
					
						
							|  |  |  | // codes.Unknown if err is non-nil and not a context error. | 
					
						
							|  |  |  | func FromContextError(err error) *Status { | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if errors.Is(err, context.DeadlineExceeded) { | 
					
						
							|  |  |  | 		return New(codes.DeadlineExceeded, err.Error()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if errors.Is(err, context.Canceled) { | 
					
						
							|  |  |  | 		return New(codes.Canceled, err.Error()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return New(codes.Unknown, err.Error()) | 
					
						
							|  |  |  | } |