github.com/lastbackend/toolkit@v0.0.0-20241020043710-cafa37b95aad/pkg/server/http/errors/http.go (about) 1 package errors 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 8 "google.golang.org/grpc/codes" 9 "google.golang.org/grpc/status" 10 ) 11 12 var GrpcErrorHandlerFunc = HTTP.ParseGrpcError 13 var HTTP Http 14 15 type Http struct { 16 Code int `json:"code"` 17 Status string `json:"status"` 18 Message string `json:"message"` 19 } 20 21 func (Http) Unauthorized(w http.ResponseWriter, msg ...string) { 22 HTTP.getUnauthorized(msg...).send(w) 23 } 24 25 func (Http) Forbidden(w http.ResponseWriter, msg ...string) { 26 HTTP.getForbidden(msg...).send(w) 27 } 28 29 func (Http) NotAllowed(w http.ResponseWriter, msg ...string) { 30 HTTP.getNotAllowed(msg...).send(w) 31 } 32 33 func (Http) BadRequest(w http.ResponseWriter, msg ...string) { 34 HTTP.getBadRequest(msg...).send(w) 35 } 36 37 func (Http) NotFound(w http.ResponseWriter, args ...string) { 38 HTTP.getNotFound(args...).send(w) 39 } 40 41 func (Http) InternalServerError(w http.ResponseWriter, msg ...string) { 42 HTTP.getInternalServerError(msg...).send(w) 43 } 44 45 func (Http) BadGateway(w http.ResponseWriter) { 46 HTTP.getBadGateway().send(w) 47 } 48 49 func (Http) PaymentRequired(w http.ResponseWriter, msg ...string) { 50 HTTP.getPaymentRequired(msg...).send(w) 51 } 52 53 func (Http) NotImplemented(w http.ResponseWriter, msg ...string) { 54 HTTP.getPaymentRequired(msg...).send(w) 55 } 56 57 func (Http) BadParameter(w http.ResponseWriter, args ...string) { 58 HTTP.getBadParameter(args...).send(w) 59 } 60 61 func (Http) InvalidJSON(w http.ResponseWriter, msg ...string) { 62 HTTP.getIncorrectJSON(msg...).send(w) 63 } 64 65 func (Http) InvalidXML(w http.ResponseWriter, msg ...string) { 66 HTTP.getIncorrectXML(msg...).send(w) 67 } 68 69 func (h Http) send(w http.ResponseWriter) { 70 w.Header().Set("Content-Type", "application/json; charset=UTF-8") 71 w.WriteHeader(h.Code) 72 response, _ := json.Marshal(h) 73 w.Write(response) 74 } 75 76 // =================================================================================================================== 77 // ============================================= INTERNAL HELPER METHODS ============================================= 78 // =================================================================================================================== 79 80 func (Http) getUnauthorized(msg ...string) *Http { 81 return getHttpError(http.StatusUnauthorized, msg...) 82 } 83 84 func (Http) getForbidden(msg ...string) *Http { 85 return getHttpError(http.StatusForbidden, msg...) 86 } 87 88 func (Http) getNotAllowed(msg ...string) *Http { 89 return getHttpError(http.StatusMethodNotAllowed, msg...) 90 } 91 92 func (Http) getPaymentRequired(msg ...string) *Http { 93 return getHttpError(http.StatusPaymentRequired, msg...) 94 } 95 96 func (Http) getUnknown(msg ...string) *Http { 97 return getHttpError(http.StatusInternalServerError, msg...) 98 } 99 100 func (Http) getInternalServerError(msg ...string) *Http { 101 return getHttpError(http.StatusInternalServerError, msg...) 102 } 103 104 func (Http) getBadGateway() *Http { 105 return getHttpError(http.StatusBadGateway) 106 } 107 108 func (Http) getNotImplemented(msg ...string) *Http { 109 return getHttpError(http.StatusNotImplemented, msg...) 110 } 111 112 func (Http) getBadRequest(msg ...string) *Http { 113 return getHttpError(http.StatusBadRequest, msg...) 114 } 115 116 func (Http) getNotFound(args ...string) *Http { 117 message := "Not Found" 118 for i, a := range args { 119 switch i { 120 case 0: 121 message = fmt.Sprintf("%s not found", toUpperFirstChar(a)) 122 default: 123 panic("Wrong parameter count: (is allowed from 0 to 1)") 124 } 125 } 126 return &Http{ 127 Code: http.StatusNotFound, 128 Status: http.StatusText(http.StatusNotFound), 129 Message: message, 130 } 131 } 132 133 func (Http) getNotUnique(name string) *Http { 134 return &Http{ 135 Code: http.StatusBadRequest, 136 Status: StatusNotUnique, 137 Message: fmt.Sprintf("%s is already in use", toUpperFirstChar(name)), 138 } 139 } 140 141 func (Http) getIncorrectJSON(msg ...string) *Http { 142 message := "Incorrect json" 143 for i, m := range msg { 144 switch i { 145 case 0: 146 message = m 147 default: 148 panic("Wrong parameter count: (is allowed from 0 to 1)") 149 } 150 } 151 return &Http{ 152 Code: http.StatusBadRequest, 153 Status: StatusIncorrectJson, 154 Message: message, 155 } 156 } 157 158 func (Http) getIncorrectXML(msg ...string) *Http { 159 message := "Incorrect json" 160 for i, m := range msg { 161 switch i { 162 case 0: 163 message = m 164 default: 165 panic("Wrong parameter count: (is allowed from 0 to 1)") 166 } 167 } 168 return &Http{ 169 Code: http.StatusBadRequest, 170 Status: StatusIncorrectXml, 171 Message: message, 172 } 173 } 174 175 func (Http) getAllocatedParameter(args ...string) *Http { 176 message := "Value is in use" 177 for i, a := range args { 178 switch i { 179 case 0: 180 message = fmt.Sprintf("%s is already in use", toUpperFirstChar(a)) 181 default: 182 panic("Wrong parameter count: (is allowed from 0 to 1)") 183 } 184 } 185 return &Http{ 186 Code: http.StatusBadRequest, 187 Status: StatusBadParameter, 188 Message: message, 189 } 190 } 191 192 func (Http) getBadParameter(args ...string) *Http { 193 message := "Bad parameter" 194 for i, a := range args { 195 switch i { 196 case 0: 197 message = fmt.Sprintf("Bad %s parameter", a) 198 default: 199 panic("Wrong parameter count: (is allowed from 0 to 1)") 200 } 201 } 202 return &Http{ 203 Code: http.StatusBadRequest, 204 Status: StatusBadParameter, 205 Message: message, 206 } 207 } 208 209 func getHttpError(code int, msg ...string) *Http { 210 httpStatus := http.StatusText(code) 211 httpMessage := http.StatusText(code) 212 213 for i, m := range msg { 214 switch i { 215 case 0: 216 httpStatus = m 217 default: 218 panic("Wrong parameter count: (is allowed from 0 to 1)") 219 } 220 } 221 return &Http{ 222 Code: code, 223 Status: httpMessage, 224 Message: httpStatus, 225 } 226 } 227 228 func (h Http) ParseGrpcError(w http.ResponseWriter, err error) { 229 st, ok := status.FromError(err) 230 if !ok { 231 h.InternalServerError(w, err.Error()) 232 return 233 } 234 getHttpError(httpStatusFromCode(st.Code()), st.Message()).send(w) 235 } 236 237 func httpStatusFromCode(code codes.Code) int { 238 switch code { 239 case codes.OK: 240 return http.StatusOK 241 case codes.Canceled: 242 return http.StatusRequestTimeout 243 case codes.Unknown: 244 return http.StatusInternalServerError 245 case codes.InvalidArgument: 246 return http.StatusBadRequest 247 case codes.DeadlineExceeded: 248 return http.StatusGatewayTimeout 249 case codes.NotFound: 250 return http.StatusNotFound 251 case codes.AlreadyExists: 252 return http.StatusConflict 253 case codes.PermissionDenied: 254 return http.StatusForbidden 255 case codes.Unauthenticated: 256 return http.StatusUnauthorized 257 case codes.ResourceExhausted: 258 return http.StatusTooManyRequests 259 case codes.FailedPrecondition: 260 // Note, this deliberately 261 return http.StatusBadRequest 262 case codes.Aborted: 263 return http.StatusConflict 264 case codes.OutOfRange: 265 return http.StatusBadRequest 266 case codes.Unimplemented: 267 return http.StatusNotImplemented 268 case codes.Internal: 269 return http.StatusInternalServerError 270 case codes.Unavailable: 271 return http.StatusServiceUnavailable 272 case codes.DataLoss: 273 return http.StatusInternalServerError 274 } 275 return http.StatusInternalServerError 276 }