I have an HTTP API written in Go, and to give more fine grained responses to the client app, we return our own error codes along with the standard HTTP status codes Along a similar line to
what Twitter does with its error codes. The correct HTTP status code can always be determined from our internal error code, so any HTTP handler that wants to return an error response, only has to call our error response function, and pass in our custom error code, and from that we can determine the error message and http response that we should give in the HTTP response. What I am not sure about, is the best way to structure this.
One option is to define our error codes as constants with iota. Something like:
const (
OK int = iota + 1
ErrBadRequest
ErrRecipientNotExist
...
)
And then have some sort of switch lookup to return the HTTP response and the error message to return. Something like:
func inspectStatusCode(errCode int) (httpStatus int, errorMsg string) {
switch errCode {
case OK:
return http.StatusOK, "OK"
case ErrBadRequest:
return http.StatusBadRequest, "Poorly formatted request"
case ErrRecipientNotExist:
return http.StatusNotFound, "The entity does not exist"
...
}
...
}
This method allows me to not have to directly specify an int value for each response.
Alternatively I could define a struct that contains all of the data directly, but with an explicit response code. Something like:
type response struct {
code int
message string
httpStatus int
}
And then have a large number of global variables to reference the response. Something like:
var (
ErrBadRequest = errResp{
code: 10,
message: "Poorly formatted request",
httpStatus: http.StatusBadRequest,
}
...
)
Only here I don't like that I'm using global variables, rather than constants, and I don't like that I have to specify each error code directly (but then I'll have to do that in the documentation anyway).
Is there a better way of handling this than one of these two methods? Otherwise I'd love to get feedback on the two methods that I've described.