blob: 01e182c306c23ffa921e7374f844d4e47f26abed [file] [log] [blame]
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -07001/*
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
19// Package status implements errors returned by gRPC. These errors are
20// serialized and transmitted on the wire between server and client, and allow
21// for additional data to be transmitted via the Details field in the status
22// proto. gRPC service handlers should return an error created by this
23// package, and gRPC clients should expect a corresponding error to be
24// returned from the RPC call.
25//
26// This package upholds the invariants that a non-nil error may not
27// contain an OK code, and an OK code must result in a nil error.
28package status
29
30import (
31 "context"
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070032 "fmt"
33
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070034 spb "google.golang.org/genproto/googleapis/rpc/status"
amit.ghosh258d14c2020-10-02 15:13:38 +020035
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070036 "google.golang.org/grpc/codes"
amit.ghosh258d14c2020-10-02 15:13:38 +020037 "google.golang.org/grpc/internal/status"
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070038)
39
amit.ghosh258d14c2020-10-02 15:13:38 +020040// Status references google.golang.org/grpc/internal/status. It represents an
41// RPC status code, message, and details. It is immutable and should be
42// created with New, Newf, or FromProto.
43// https://godoc.org/google.golang.org/grpc/internal/status
44type Status = status.Status
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070045
46// New returns a Status representing c and msg.
47func New(c codes.Code, msg string) *Status {
amit.ghosh258d14c2020-10-02 15:13:38 +020048 return status.New(c, msg)
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070049}
50
51// Newf returns New(c, fmt.Sprintf(format, a...)).
52func Newf(c codes.Code, format string, a ...interface{}) *Status {
53 return New(c, fmt.Sprintf(format, a...))
54}
55
56// Error returns an error representing c and msg. If c is OK, returns nil.
57func Error(c codes.Code, msg string) error {
58 return New(c, msg).Err()
59}
60
61// Errorf returns Error(c, fmt.Sprintf(format, a...)).
62func Errorf(c codes.Code, format string, a ...interface{}) error {
63 return Error(c, fmt.Sprintf(format, a...))
64}
65
66// ErrorProto returns an error representing s. If s.Code is OK, returns nil.
67func ErrorProto(s *spb.Status) error {
68 return FromProto(s).Err()
69}
70
71// FromProto returns a Status representing s.
72func FromProto(s *spb.Status) *Status {
amit.ghosh258d14c2020-10-02 15:13:38 +020073 return status.FromProto(s)
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070074}
75
76// FromError returns a Status representing err if it was produced from this
77// package or has a method `GRPCStatus() *Status`. Otherwise, ok is false and a
78// Status is returned with codes.Unknown and the original error message.
79func FromError(err error) (s *Status, ok bool) {
80 if err == nil {
Arjun E K57a7fcb2020-01-30 06:44:45 +000081 return nil, true
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070082 }
83 if se, ok := err.(interface {
84 GRPCStatus() *Status
85 }); ok {
86 return se.GRPCStatus(), true
87 }
88 return New(codes.Unknown, err.Error()), false
89}
90
91// Convert is a convenience function which removes the need to handle the
92// boolean return value from FromError.
93func Convert(err error) *Status {
94 s, _ := FromError(err)
95 return s
96}
97
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -070098// Code returns the Code of the error if it is a Status error, codes.OK if err
99// is nil, or codes.Unknown otherwise.
100func Code(err error) codes.Code {
101 // Don't use FromError to avoid allocation of OK status.
102 if err == nil {
103 return codes.OK
104 }
105 if se, ok := err.(interface {
106 GRPCStatus() *Status
107 }); ok {
108 return se.GRPCStatus().Code()
109 }
110 return codes.Unknown
111}
112
113// FromContextError converts a context error into a Status. It returns a
114// Status with codes.OK if err is nil, or a Status with codes.Unknown if err is
115// non-nil and not a context error.
116func FromContextError(err error) *Status {
117 switch err {
118 case nil:
Arjun E K57a7fcb2020-01-30 06:44:45 +0000119 return nil
Matteo Scandoloa6a3aee2019-11-26 13:30:14 -0700120 case context.DeadlineExceeded:
121 return New(codes.DeadlineExceeded, err.Error())
122 case context.Canceled:
123 return New(codes.Canceled, err.Error())
124 default:
125 return New(codes.Unknown, err.Error())
126 }
127}