Ответ
gRPC имеет собственный набор стандартных кодов состояния, которые более детальны, чем HTTP-статусы. Они определены в пакете google.golang.org/grpc/codes
.
Ключевое отличие от REST API:
Даже если gRPC-вызов завершился с ошибкой (например, NotFound
), HTTP-статус транспортного уровня чаще всего будет 200 OK
. Сам gRPC-статус передается в трейлерах (trailers) HTTP/2 ответа, обычно в заголовках grpc-status
и grpc-message
.
Основные коды статусов:
OK
(0): Запрос успешно выполнен.Canceled
(1): Операция была отменена клиентом.InvalidArgument
(3): Клиент указал неверный аргумент (например, ошибка валидации).DeadlineExceeded
(4): Время выполнения операции истекло до её завершения.NotFound
(5): Запрошенный ресурс не найден.AlreadyExists
(6): Попытка создать ресурс, который уже существует.PermissionDenied
(7): У клиента нет прав для выполнения этой операции.Unauthenticated
(16): Запрос не содержит валидных данных для аутентификации.ResourceExhausted
(8): Ресурс исчерпан (например, превышена квота).Unavailable
(14): Сервис временно недоступен. Клиенту рекомендуется повторить попытку позже.Internal
(13): Внутренняя ошибка сервера. Не следует раскрывать детали этой ошибки клиенту.Unknown
(2): Неизвестная ошибка.
Пример использования в Go:
Сервер (возврат стандартной ошибки):
import (
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func (s *Server) GetUser(ctx context.Context, req *pb.UserRequest) (*pb.User, error) {
user, err := db.FindUser(req.Id)
if err == sql.ErrNoRows {
// Возвращаем стандартный статус NotFound
return nil, status.Errorf(codes.NotFound, "user with id '%s' not found", req.Id)
}
// ...
}
Клиент (проверка статуса):
// ... после вызова RPC
if err != nil {
st, ok := status.FromError(err)
if ok {
// Это gRPC ошибка
if st.Code() == codes.NotFound {
log.Println("Пользователь не найден, обрабатываем этот случай.")
} else {
log.Printf("gRPC ошибка: код=%s, сообщение=%s", st.Code(), st.Message())
}
} else {
// Это не gRPC ошибка (например, проблема с сетью)
log.Printf("Неизвестная ошибка: %v", err)
}
}