github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/pkg/jsonapi/errors.go (about) 1 package jsonapi 2 3 import ( 4 "fmt" 5 "net/http" 6 "strconv" 7 ) 8 9 // SourceError contains references to the source of the error 10 type SourceError struct { 11 Pointer string `json:"pointer,omitempty"` 12 Parameter string `json:"parameter,omitempty"` 13 } 14 15 // Error objects provide additional information about problems encountered 16 // while performing an operation. 17 // See http://jsonapi.org/format/#error-objects 18 type Error struct { 19 Status int `json:"status,string"` 20 Title string `json:"title"` 21 Code string `json:"code,omitempty"` 22 Detail string `json:"detail,omitempty"` 23 Source SourceError `json:"source,omitempty"` 24 Links *LinksList `json:"links,omitempty"` 25 } 26 27 // ErrorList is just an array of error objects 28 type ErrorList []*Error 29 30 func (e *Error) Error() string { 31 return e.Title + "(" + strconv.Itoa(e.Status) + ")" + ": " + e.Detail 32 } 33 34 // NewError creates a new generic Error 35 func NewError(status int, detail string) *Error { 36 return &Error{ 37 Status: status, 38 Title: http.StatusText(status), 39 Detail: detail, 40 } 41 } 42 43 // Errorf creates a new generic Error with detail build as Sprintf 44 func Errorf(status int, format string, args ...interface{}) *Error { 45 detail := fmt.Sprintf(format, args...) 46 return NewError(status, detail) 47 } 48 49 // NotFound returns a 404 formatted error 50 func NotFound(err error) *Error { 51 return &Error{ 52 Status: http.StatusNotFound, 53 Title: "Not Found", 54 Detail: err.Error(), 55 } 56 } 57 58 // BadRequest returns a 400 formatted error 59 func BadRequest(err error) *Error { 60 return &Error{ 61 Status: http.StatusBadRequest, 62 Title: "Bad Request", 63 Detail: err.Error(), 64 } 65 } 66 67 // Unauthorized returns a 401 formatted error 68 func Unauthorized(err error) *Error { 69 return &Error{ 70 Status: http.StatusUnauthorized, 71 Title: "Unauthorized", 72 Detail: err.Error(), 73 } 74 } 75 76 // BadJSON returns a 400 formatted error meaning the json input is 77 // malformed. 78 func BadJSON() *Error { 79 return &Error{ 80 Status: http.StatusBadRequest, 81 Title: "Bad Request", 82 Detail: "JSON input is malformed or is missing mandatory fields", 83 } 84 } 85 86 // MethodNotAllowed returns a 405 formatted error 87 func MethodNotAllowed(method string) *Error { 88 return &Error{ 89 Status: http.StatusMethodNotAllowed, 90 Title: "Method Not Allowed", 91 Detail: method + " is not allowed on this endpoint", 92 } 93 } 94 95 // Conflict returns a 409 formatted error representing a conflict 96 func Conflict(err error) *Error { 97 return &Error{ 98 Status: http.StatusConflict, 99 Title: "Conflict", 100 Detail: err.Error(), 101 } 102 } 103 104 // InternalServerError returns a 500 formatted error 105 func InternalServerError(err error) *Error { 106 return &Error{ 107 Status: http.StatusInternalServerError, 108 Title: "Internal Server Error", 109 Detail: err.Error(), 110 } 111 } 112 113 // PreconditionFailed returns a 412 formatted error when an expectation from an 114 // HTTP header is not matched 115 func PreconditionFailed(parameter string, err error) *Error { 116 return &Error{ 117 Status: http.StatusPreconditionFailed, 118 Title: "Precondition Failed", 119 Detail: err.Error(), 120 Source: SourceError{ 121 Parameter: parameter, 122 }, 123 } 124 } 125 126 // InvalidParameter returns a 422 formatted error when an HTTP or Query-String 127 // parameter is invalid 128 func InvalidParameter(parameter string, err error) *Error { 129 return &Error{ 130 Status: http.StatusUnprocessableEntity, 131 Title: "Invalid Parameter", 132 Detail: err.Error(), 133 Source: SourceError{ 134 Parameter: parameter, 135 }, 136 } 137 } 138 139 // InvalidAttribute returns a 422 formatted error when an attribute is invalid 140 func InvalidAttribute(attribute string, err error) *Error { 141 return &Error{ 142 Status: http.StatusUnprocessableEntity, 143 Title: "Invalid Attribute", 144 Detail: err.Error(), 145 Source: SourceError{ 146 Pointer: "/data/attributes/" + attribute, 147 }, 148 } 149 } 150 151 // Forbidden returns a 403 Forbidden error formatted when an action is 152 // fobidden. 153 func Forbidden(err error) *Error { 154 return &Error{ 155 Status: http.StatusForbidden, 156 Title: "Forbidden", 157 Detail: err.Error(), 158 } 159 } 160 161 // BadGateway returns a 502 formatted error 162 func BadGateway(err error) *Error { 163 return &Error{ 164 Status: http.StatusBadGateway, 165 Title: "Bad Gateway", 166 Detail: err.Error(), 167 } 168 }