github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/api/server/httputils/errors.go (about) 1 package httputils 2 3 import ( 4 "net/http" 5 "strings" 6 7 "github.com/Sirupsen/logrus" 8 ) 9 10 // httpStatusError is an interface 11 // that errors with custom status codes 12 // implement to tell the api layer 13 // which response status to set. 14 type httpStatusError interface { 15 HTTPErrorStatusCode() int 16 } 17 18 // inputValidationError is an interface 19 // that errors generated by invalid 20 // inputs can implement to tell the 21 // api layer to set a 400 status code 22 // in the response. 23 type inputValidationError interface { 24 IsValidationError() bool 25 } 26 27 // GetHTTPErrorStatusCode retrieve status code from error message 28 func GetHTTPErrorStatusCode(err error) int { 29 if err == nil { 30 logrus.WithFields(logrus.Fields{"error": err}).Error("unexpected HTTP error handling") 31 return http.StatusInternalServerError 32 } 33 34 var statusCode int 35 errMsg := err.Error() 36 37 switch e := err.(type) { 38 case httpStatusError: 39 statusCode = e.HTTPErrorStatusCode() 40 case inputValidationError: 41 statusCode = http.StatusBadRequest 42 default: 43 // FIXME: this is brittle and should not be necessary, but we still need to identify if 44 // there are errors falling back into this logic. 45 // If we need to differentiate between different possible error types, 46 // we should create appropriate error types that implement the httpStatusError interface. 47 errStr := strings.ToLower(errMsg) 48 for keyword, status := range map[string]int{ 49 "not found": http.StatusNotFound, 50 "no such": http.StatusNotFound, 51 "bad parameter": http.StatusBadRequest, 52 "conflict": http.StatusConflict, 53 "impossible": http.StatusNotAcceptable, 54 "wrong login/password": http.StatusUnauthorized, 55 "hasn't been activated": http.StatusForbidden, 56 } { 57 if strings.Contains(errStr, keyword) { 58 statusCode = status 59 break 60 } 61 } 62 } 63 64 if statusCode == 0 { 65 statusCode = http.StatusInternalServerError 66 } 67 68 return statusCode 69 } 70 71 // WriteError decodes a specific docker error and sends it in the response. 72 func WriteError(w http.ResponseWriter, err error) { 73 if err == nil || w == nil { 74 logrus.WithFields(logrus.Fields{"error": err, "writer": w}).Error("unexpected HTTP error handling") 75 return 76 } 77 78 statusCode := GetHTTPErrorStatusCode(err) 79 http.Error(w, err.Error(), statusCode) 80 }