192 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			192 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // 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"
 | |
| )
 | |
| 
 | |
| 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())
 | |
| }
 |