/
githubmirror
/
client
Обзор
Документация
Войти
/
githubmirror
/
client
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
go/kbfs/kbfsblock/server_errors.go
367 строк
11 KB
zoom-ua
modernize error handling with errors.As/Is (#29350)
25 июн 2026, 17:41
Не верифицирован
25 июн 2026, 17:41
e09e254
Код
Авторство
О чём код?
// Copyright 2016 Keybase Inc. All rights reserved. // Use of this source code is governed by a BSD // license that can be found in the LICENSE file. package kbfsblock import ( "errors" "fmt" "strconv" "github.com/keybase/client/go/libkb" "github.com/keybase/client/go/protocol/keybase1" "github.com/keybase/go-framed-msgpack-rpc/rpc" ) const ( // StatusCodeServerError is the error code for a generic block server error. StatusCodeServerError = 2700 // StatusCodeServerErrorBadRequest is the error code for a generic client error. StatusCodeServerErrorBadRequest = 2701 // StatusCodeServerErrorUnauthorized is the error code for when the session has not been validated StatusCodeServerErrorUnauthorized = 2702 // StatusCodeServerErrorOverQuota is the error code for when the user has exceeded his quota StatusCodeServerErrorOverQuota = 2703 // StatusCodeServerErrorBlockNonExistent is the error code for when bserver cannot find a block StatusCodeServerErrorBlockNonExistent = 2704 // StatusCodeServerErrorBlockArchived is the error code for a block has been archived StatusCodeServerErrorBlockArchived = 2705 // StatusCodeServerErrorNoPermission is the error code for when there's no permission StatusCodeServerErrorNoPermission = 2706 // StatusCodeServerErrorBlockDeleted is the error code for a block has been deleted StatusCodeServerErrorBlockDeleted = 2707 // StatusCodeServerErrorNonceNonExistent is the error code when a nonce cannot be found StatusCodeServerErrorNonceNonExistent = 2708 // StatusCodeServerErrorMaxRefExceeded is the error code to indicate there are too many refs to a block StatusCodeServerErrorMaxRefExceeded = 2709 // StatusCodeServerErrorThrottle is the error code to indicate the client should initiate backoff. StatusCodeServerErrorThrottle = 2799 ) // ServerError is a generic bserver-side error. type ServerError struct { Msg string } // ToStatus implements the ExportableError interface for ServerError. func (e ServerError) ToStatus() (s keybase1.Status) { s.Code = StatusCodeServerError s.Name = "SERVER_ERROR" s.Desc = e.Msg return } // Error implements the Error interface for ServerError. func (e ServerError) Error() string { return "ServerError{" + e.Msg + "}" } // ServerErrorBadRequest is a generic client-side error. type ServerErrorBadRequest struct { Msg string } // ToStatus implements the ExportableError interface for ServerError. func (e ServerErrorBadRequest) ToStatus() (s keybase1.Status) { s.Code = StatusCodeServerErrorBadRequest s.Name = "BAD_REQUEST" s.Desc = e.Msg return } // Error implements the Error interface for ServerError. func (e ServerErrorBadRequest) Error() string { if e.Msg == "" { return "Server: bad client request" } return "ServerErrorBadRequest{" + e.Msg + "}" } // ServerErrorUnauthorized is a generic client-side error. type ServerErrorUnauthorized struct { Msg string } // ToStatus implements the ExportableError interface for ServerErrorUnauthorized. func (e ServerErrorUnauthorized) ToStatus() (s keybase1.Status) { s.Code = StatusCodeServerErrorUnauthorized s.Name = "SESSION_UNAUTHORIZED" s.Desc = e.Msg return } // Error implements the Error interface for ServerErrorUnauthorized. func (e ServerErrorUnauthorized) Error() string { if e.Msg == "" { return "Server: session not validated" } return "ServerErrorUnauthorized{" + e.Msg + "}" } // ServerErrorOverQuota is returned when a user is over quota. type ServerErrorOverQuota struct { Msg string // Usage indicates the current usage Usage int64 // Limit indicates the current quota limit Limit int64 // Throttled indicates if request has not been completed due to server throttle Throttled bool } // ToStatus implements the ExportableError interface for ServerErrorOverQuota. func (e ServerErrorOverQuota) ToStatus() (s keybase1.Status) { s.Code = StatusCodeServerErrorOverQuota s.Name = "QUOTA_EXCEEDED" s.Desc = e.Msg s.Fields = append(s.Fields, keybase1.StringKVPair{ Key: "QUOTA_USAGE", Value: strconv.FormatInt(e.Usage, 10), }) s.Fields = append(s.Fields, keybase1.StringKVPair{ Key: "QUOTA_LIMIT", Value: strconv.FormatInt(e.Limit, 10), }) s.Fields = append(s.Fields, keybase1.StringKVPair{ Key: "QUOTA_THROTTLE", Value: strconv.FormatBool(e.Throttled), }) return } // Error implements the Error interface for ServerErrorOverQuota. func (e ServerErrorOverQuota) Error() string { return fmt.Sprintf( "ServerErrorOverQuota{Msg: %q, Usage: %d, Limit: %d, Throttled: %t}", e.Msg, e.Usage, e.Limit, e.Throttled) } // ServerErrorBlockNonExistent is an exportable error from bserver type ServerErrorBlockNonExistent struct { Msg string } // ToStatus implements the ExportableError interface for ServerErrorBlockNonExistent func (e ServerErrorBlockNonExistent) ToStatus() (s keybase1.Status) { s.Code = StatusCodeServerErrorBlockNonExistent s.Name = "BLOCK_NONEXISTENT" s.Desc = e.Msg return } // Error implements the Error interface for ServerErrorBlockNonExistent. func (e ServerErrorBlockNonExistent) Error() string { if e.Msg == "" { return "Server: block does not exist" } return "ServerErrorBlockNonExistent{" + e.Msg + "}" } // ServerErrorBlockArchived is an exportable error from bserver type ServerErrorBlockArchived struct { Msg string } // ToStatus implements the ExportableError interface for ServerErrorBlockArchived func (e ServerErrorBlockArchived) ToStatus() (s keybase1.Status) { s.Code = StatusCodeServerErrorBlockArchived s.Name = "BLOCK_ARCHIVED" s.Desc = e.Msg return } // Error implements the Error interface for ServerErrorBlockArchived. func (e ServerErrorBlockArchived) Error() string { if e.Msg == "" { return "Server: block is archived" } return "ServerErrorBlockArchived{" + e.Msg + "}" } // ServerErrorBlockDeleted is an exportable error from bserver type ServerErrorBlockDeleted struct { Msg string } // ToStatus implements the ExportableError interface for ServerErrorBlockDeleted func (e ServerErrorBlockDeleted) ToStatus() (s keybase1.Status) { s.Code = StatusCodeServerErrorBlockDeleted s.Name = "BLOCK_DELETED" s.Desc = e.Msg return } // Error implements the Error interface for ServerErrorBlockDeleted func (e ServerErrorBlockDeleted) Error() string { if e.Msg == "" { return "Server: block is deleted" } return "ServerErrorBlockDeleted{" + e.Msg + "}" } // ServerErrorNoPermission is an exportable error from bserver type ServerErrorNoPermission struct { Msg string } // ToStatus implements the ExportableError interface for ServerErrorBlockArchived func (e ServerErrorNoPermission) ToStatus() (s keybase1.Status) { s.Code = StatusCodeServerErrorNoPermission s.Name = "NO_PERMISSION" s.Desc = e.Msg return } // Error implements the Error interface for ServerErrorNoPermission. func (e ServerErrorNoPermission) Error() string { if e.Msg == "" { return "Server: permission denied" } return "ServerErrorNoPermission{" + e.Msg + "}" } // ServerErrorNonceNonExistent is an exportable error from bserver type ServerErrorNonceNonExistent struct { Msg string } // ToStatus implements the ExportableError interface for ServerErrorNonceNonExistent func (e ServerErrorNonceNonExistent) ToStatus() (s keybase1.Status) { s.Code = StatusCodeServerErrorNonceNonExistent s.Name = "BLOCK_NONCENONEXISTENT" s.Desc = e.Msg return } // Error implements the Error interface for ServerErrornonceNonExistent. func (e ServerErrorNonceNonExistent) Error() string { if e.Msg == "" { return "Server: reference nonce does not exist" } return "ServerErrorNonceNonExistent{" + e.Msg + "}" } // ServerErrorMaxRefExceeded is an exportable error from bserver type ServerErrorMaxRefExceeded struct { Msg string } // ToStatus implements the ExportableError interface for ServerErrorMaxRefExceeded func (e ServerErrorMaxRefExceeded) ToStatus() (s keybase1.Status) { s.Code = StatusCodeServerErrorMaxRefExceeded s.Name = "BLOCK_MAXREFEXCEEDED" s.Desc = e.Msg return } // Error implements the Error interface for ServerErrorMaxRefExceeded func (e ServerErrorMaxRefExceeded) Error() string { if e.Msg == "" { return "Server: maximum allowed number of references exceeded" } return "ServerErrorMaxRefExceeded{" + e.Msg + "}" } // ServerErrorThrottle is returned when the server wants the client to backoff. type ServerErrorThrottle struct { Msg string } // Error implements the Error interface for ServerErrorThrottle. func (e ServerErrorThrottle) Error() string { return "ServerErrorThrottle{" + e.Msg + "}" } // ToStatus implements the ExportableError interface for ServerErrorThrottle. func (e ServerErrorThrottle) ToStatus() (s keybase1.Status) { s.Code = StatusCodeServerErrorThrottle s.Name = "ERROR_THROTTLE" s.Desc = e.Msg return } // ServerErrorUnwrapper unwraps errors from a remote block server. type ServerErrorUnwrapper struct{} var _ rpc.ErrorUnwrapper = ServerErrorUnwrapper{} // MakeArg implements rpc.ErrorUnwrapper. func (eu ServerErrorUnwrapper) MakeArg() any { return &keybase1.Status{} } // UnwrapError implements rpc.ErrorUnwrapper. func (eu ServerErrorUnwrapper) UnwrapError(arg any) (appError error, dispatchError error) { s, ok := arg.(*keybase1.Status) if !ok { return nil, errors.New("Error converting arg to keybase1.Status object in ServerErrorUnwrapper.UnwrapError") } if s == nil || s.Code == 0 { return nil, nil } switch s.Code { case StatusCodeServerError: appError = ServerError{Msg: s.Desc} case StatusCodeServerErrorBadRequest: appError = ServerErrorBadRequest{Msg: s.Desc} case StatusCodeServerErrorUnauthorized: appError = ServerErrorUnauthorized{Msg: s.Desc} case StatusCodeServerErrorOverQuota: quotaErr := ServerErrorOverQuota{Msg: s.Desc} for _, f := range s.Fields { switch f.Key { case "QUOTA_USAGE": quotaErr.Usage, _ = strconv.ParseInt(f.Value, 10, 64) case "QUOTA_LIMIT": quotaErr.Limit, _ = strconv.ParseInt(f.Value, 10, 64) case "QUOTA_THROTTLE": quotaErr.Throttled, _ = strconv.ParseBool(f.Value) } } appError = quotaErr case StatusCodeServerErrorBlockNonExistent: appError = ServerErrorBlockNonExistent{Msg: s.Desc} case StatusCodeServerErrorBlockArchived: appError = ServerErrorBlockArchived{Msg: s.Desc} case StatusCodeServerErrorNoPermission: appError = ServerErrorNoPermission{Msg: s.Desc} case StatusCodeServerErrorThrottle: appError = ServerErrorThrottle{Msg: s.Desc} case StatusCodeServerErrorBlockDeleted: appError = ServerErrorBlockDeleted{Msg: s.Desc} case StatusCodeServerErrorNonceNonExistent: appError = ServerErrorNonceNonExistent{Msg: s.Desc} case StatusCodeServerErrorMaxRefExceeded: appError = ServerErrorMaxRefExceeded{Msg: s.Desc} default: ase := libkb.AppStatusError{ Code: s.Code, Name: s.Name, Desc: s.Desc, Fields: make(map[string]string), } for _, f := range s.Fields { ase.Fields[f.Key] = f.Value } appError = ase } return appError, nil } // IsThrottleError returns whether or not the given error signals // throttling. func IsThrottleError(err error) bool { var throttleErr ServerErrorThrottle if errors.As(err, &throttleErr) { return true } var quotaErr ServerErrorOverQuota if errors.As(err, "aErr) && quotaErr.Throttled { return true } return false }