github.com/cozy/cozy-stack@v0.0.0-20240327093429-939e4a21320e/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 // BadJSON returns a 400 formatted error meaning the json input is 68 // malformed. 69 func BadJSON() *Error { 70 return &Error{ 71 Status: http.StatusBadRequest, 72 Title: "Bad Request", 73 Detail: "JSON input is malformed or is missing mandatory fields", 74 } 75 } 76 77 // MethodNotAllowed returns a 405 formatted error 78 func MethodNotAllowed(method string) *Error { 79 return &Error{ 80 Status: http.StatusMethodNotAllowed, 81 Title: "Method Not Allowed", 82 Detail: method + " is not allowed on this endpoint", 83 } 84 } 85 86 // Conflict returns a 409 formatted error representing a conflict 87 func Conflict(err error) *Error { 88 return &Error{ 89 Status: http.StatusConflict, 90 Title: "Conflict", 91 Detail: err.Error(), 92 } 93 } 94 95 // InternalServerError returns a 500 formatted error 96 func InternalServerError(err error) *Error { 97 return &Error{ 98 Status: http.StatusInternalServerError, 99 Title: "Internal Server Error", 100 Detail: err.Error(), 101 } 102 } 103 104 // PreconditionFailed returns a 412 formatted error when an expectation from an 105 // HTTP header is not matched 106 func PreconditionFailed(parameter string, err error) *Error { 107 return &Error{ 108 Status: http.StatusPreconditionFailed, 109 Title: "Precondition Failed", 110 Detail: err.Error(), 111 Source: SourceError{ 112 Parameter: parameter, 113 }, 114 } 115 } 116 117 // InvalidParameter returns a 422 formatted error when an HTTP or Query-String 118 // parameter is invalid 119 func InvalidParameter(parameter string, err error) *Error { 120 return &Error{ 121 Status: http.StatusUnprocessableEntity, 122 Title: "Invalid Parameter", 123 Detail: err.Error(), 124 Source: SourceError{ 125 Parameter: parameter, 126 }, 127 } 128 } 129 130 // InvalidAttribute returns a 422 formatted error when an attribute is invalid 131 func InvalidAttribute(attribute string, err error) *Error { 132 return &Error{ 133 Status: http.StatusUnprocessableEntity, 134 Title: "Invalid Attribute", 135 Detail: err.Error(), 136 Source: SourceError{ 137 Pointer: "/data/attributes/" + attribute, 138 }, 139 } 140 } 141 142 // Forbidden returns a 403 Forbidden error formatted when an action is 143 // fobidden. 144 func Forbidden(err error) *Error { 145 return &Error{ 146 Status: http.StatusForbidden, 147 Title: "Forbidden", 148 Detail: err.Error(), 149 } 150 } 151 152 // BadGateway returns a 502 formatted error 153 func BadGateway(err error) *Error { 154 return &Error{ 155 Status: http.StatusBadGateway, 156 Title: "Bad Gateway", 157 Detail: err.Error(), 158 } 159 }