2026-04-04 01:28:57 +08:00

59 lines
1.3 KiB
Go

package apperr
import (
"errors"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// Error 表示网关内部统一业务错误。
type Error struct {
Status int
Code string
Message string
}
func (e *Error) Error() string {
return e.Message
}
// New 构造一个统一错误,便于 HTTP 层直接映射。
func New(status int, code string, message string) *Error {
return &Error{
Status: status,
Code: code,
Message: message,
}
}
// Resolve 将任意错误转换成统一 HTTP 状态码和错误码。
func Resolve(err error) (statusCode int, code string, message string) {
if err == nil {
return 200, "ok", "ok"
}
var appErr *Error
if errors.As(err, &appErr) {
return appErr.Status, appErr.Code, appErr.Message
}
grpcStatus, ok := status.FromError(err)
if !ok {
return 500, "internal_error", "internal server error"
}
switch grpcStatus.Code() {
case codes.InvalidArgument:
return 400, "bad_request", grpcStatus.Message()
case codes.Unauthenticated, codes.PermissionDenied:
return 401, "unauthorized", grpcStatus.Message()
case codes.NotFound:
return 404, "not_found", grpcStatus.Message()
case codes.DeadlineExceeded:
return 504, "upstream_timeout", "upstream request timeout"
default:
return 502, "upstream_error", grpcStatus.Message()
}
}