status.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. /*
  2. *
  3. * Copyright 2017 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. // Package status implements errors returned by gRPC. These errors are
  19. // serialized and transmitted on the wire between server and client, and allow
  20. // for additional data to be transmitted via the Details field in the status
  21. // proto. gRPC service handlers should return an error created by this
  22. // package, and gRPC clients should expect a corresponding error to be
  23. // returned from the RPC call.
  24. //
  25. // This package upholds the invariants that a non-nil error may not
  26. // contain an OK code, and an OK code must result in a nil error.
  27. package status
  28. import (
  29. "fmt"
  30. "github.com/golang/protobuf/proto"
  31. spb "google.golang.org/genproto/googleapis/rpc/status"
  32. "google.golang.org/grpc/codes"
  33. )
  34. // statusError is an alias of a status proto. It implements error and Status,
  35. // and a nil statusError should never be returned by this package.
  36. type statusError spb.Status
  37. func (se *statusError) Error() string {
  38. p := (*spb.Status)(se)
  39. return fmt.Sprintf("rpc error: code = %s desc = %s", codes.Code(p.GetCode()), p.GetMessage())
  40. }
  41. func (se *statusError) status() *Status {
  42. return &Status{s: (*spb.Status)(se)}
  43. }
  44. // Status represents an RPC status code, message, and details. It is immutable
  45. // and should be created with New, Newf, or FromProto.
  46. type Status struct {
  47. s *spb.Status
  48. }
  49. // Code returns the status code contained in s.
  50. func (s *Status) Code() codes.Code {
  51. if s == nil || s.s == nil {
  52. return codes.OK
  53. }
  54. return codes.Code(s.s.Code)
  55. }
  56. // Message returns the message contained in s.
  57. func (s *Status) Message() string {
  58. if s == nil || s.s == nil {
  59. return ""
  60. }
  61. return s.s.Message
  62. }
  63. // Proto returns s's status as an spb.Status proto message.
  64. func (s *Status) Proto() *spb.Status {
  65. if s == nil {
  66. return nil
  67. }
  68. return proto.Clone(s.s).(*spb.Status)
  69. }
  70. // Err returns an immutable error representing s; returns nil if s.Code() is
  71. // OK.
  72. func (s *Status) Err() error {
  73. if s.Code() == codes.OK {
  74. return nil
  75. }
  76. return (*statusError)(s.s)
  77. }
  78. // New returns a Status representing c and msg.
  79. func New(c codes.Code, msg string) *Status {
  80. return &Status{s: &spb.Status{Code: int32(c), Message: msg}}
  81. }
  82. // Newf returns New(c, fmt.Sprintf(format, a...)).
  83. func Newf(c codes.Code, format string, a ...interface{}) *Status {
  84. return New(c, fmt.Sprintf(format, a...))
  85. }
  86. // Error returns an error representing c and msg. If c is OK, returns nil.
  87. func Error(c codes.Code, msg string) error {
  88. return New(c, msg).Err()
  89. }
  90. // Errorf returns Error(c, fmt.Sprintf(format, a...)).
  91. func Errorf(c codes.Code, format string, a ...interface{}) error {
  92. return Error(c, fmt.Sprintf(format, a...))
  93. }
  94. // ErrorProto returns an error representing s. If s.Code is OK, returns nil.
  95. func ErrorProto(s *spb.Status) error {
  96. return FromProto(s).Err()
  97. }
  98. // FromProto returns a Status representing s.
  99. func FromProto(s *spb.Status) *Status {
  100. return &Status{s: proto.Clone(s).(*spb.Status)}
  101. }
  102. // FromError returns a Status representing err if it was produced from this
  103. // package, otherwise it returns nil, false.
  104. func FromError(err error) (s *Status, ok bool) {
  105. if err == nil {
  106. return &Status{s: &spb.Status{Code: int32(codes.OK)}}, true
  107. }
  108. if s, ok := err.(*statusError); ok {
  109. return s.status(), true
  110. }
  111. return nil, false
  112. }