// Package errors provides a way to return detailed information // for an RPC request error. The error is normally JSON encoded. package errors import ( "encoding/json" "fmt" "net/http" ) var ( ErrBadRequest = &Error{Code: 400} ErrUnauthorized = &Error{Code: 401} ErrForbidden = &Error{Code: 403} ErrNotFound = &Error{Code: 404} ErrMethodNotAllowed = &Error{Code: 405} ErrTimeout = &Error{Code: 408} ErrConflict = &Error{Code: 409} ErrInternalServerError = &Error{Code: 500} ErNotImplemented = &Error{Code: 501} ErrBadGateway = &Error{Code: 502} ErrServiceUnavailable = &Error{Code: 503} ErrGatewayTimeout = &Error{Code: 504} ) type Error struct { Id string Code int32 Detail string Status string } func (e *Error) Error() string { b, _ := json.Marshal(e) return string(b) } // New generates a custom error. func New(id, detail string, code int32) error { return &Error{ Id: id, Code: code, Detail: detail, Status: http.StatusText(int(code)), } } // Parse tries to parse a JSON string into an error. If that // fails, it will set the given string as the error detail. func Parse(err string) *Error { e := new(Error) errr := json.Unmarshal([]byte(err), e) if errr != nil { e.Detail = err } return e } // BadRequest generates a 400 error. func BadRequest(id, format string, a ...interface{}) error { return &Error{ Id: id, Code: 400, Detail: fmt.Sprintf(format, a...), Status: http.StatusText(400), } } // Unauthorized generates a 401 error. func Unauthorized(id, format string, a ...interface{}) error { return &Error{ Id: id, Code: 401, Detail: fmt.Sprintf(format, a...), Status: http.StatusText(401), } } // Forbidden generates a 403 error. func Forbidden(id, format string, a ...interface{}) error { return &Error{ Id: id, Code: 403, Detail: fmt.Sprintf(format, a...), Status: http.StatusText(403), } } // NotFound generates a 404 error. func NotFound(id, format string, a ...interface{}) error { return &Error{ Id: id, Code: 404, Detail: fmt.Sprintf(format, a...), Status: http.StatusText(404), } } // MethodNotAllowed generates a 405 error. func MethodNotAllowed(id, format string, a ...interface{}) error { return &Error{ Id: id, Code: 405, Detail: fmt.Sprintf(format, a...), Status: http.StatusText(405), } } // Timeout generates a 408 error. func Timeout(id, format string, a ...interface{}) error { return &Error{ Id: id, Code: 408, Detail: fmt.Sprintf(format, a...), Status: http.StatusText(408), } } // Conflict generates a 409 error. func Conflict(id, format string, a ...interface{}) error { return &Error{ Id: id, Code: 409, Detail: fmt.Sprintf(format, a...), Status: http.StatusText(409), } } // InternalServerError generates a 500 error. func InternalServerError(id, format string, a ...interface{}) error { return &Error{ Id: id, Code: 500, Detail: fmt.Sprintf(format, a...), Status: http.StatusText(500), } } // NotImplemented generates a 501 error func NotImplemented(id, format string, a ...interface{}) error { return &Error{ Id: id, Code: 501, Detail: fmt.Sprintf(format, a...), Status: http.StatusText(501), } } // BadGateway generates a 502 error func BadGateway(id, format string, a ...interface{}) error { return &Error{ Id: id, Code: 502, Detail: fmt.Sprintf(format, a...), Status: http.StatusText(502), } } // ServiceUnavailable generates a 503 error func ServiceUnavailable(id, format string, a ...interface{}) error { return &Error{ Id: id, Code: 503, Detail: fmt.Sprintf(format, a...), Status: http.StatusText(503), } } // GatewayTimeout generates a 504 error func GatewayTimeout(id, format string, a ...interface{}) error { return &Error{ Id: id, Code: 504, Detail: fmt.Sprintf(format, a...), Status: http.StatusText(504), } } // Equal tries to compare errors func Equal(err1 error, err2 error) bool { verr1, ok1 := err1.(*Error) verr2, ok2 := err2.(*Error) if ok1 != ok2 { return false } if !ok1 { return err1 == err2 } if verr1.Code != verr2.Code { return false } return true } // FromError try to convert go error to *Error func FromError(err error) *Error { if verr, ok := err.(*Error); ok && verr != nil { return verr } return Parse(err.Error()) }