// deal makes the response in error cases somewhat nicer. It will try // to figure out what actually went wrong and inform the user. // It should not be called if the request went fine. If status is below // 400, and err is not nil, it will assume an internal server error. // Generally, if you pass a nil error, don't expect deal to do anything // useful. func deal(ctx context.Context, w http.ResponseWriter, r *http.Request, status int, err error) { // Getting an error and a status code blow 400 is somewhat paradox. // Also, if the status is the zero value, assume that we're dealing // with an internal server error. if err != nil && status < 400 || status == 0 { status = http.StatusInternalServerError } msg := "Sorry, Coduno encountered an error: " + http.StatusText(status) + "\n\n" msg += "If you think this is a bug, please consider filing\n" msg += "it at https://github.com/coduno/api/issues\n\n" if ctx != nil { msg += "Your request ID is " + appengine.RequestID(ctx) + " (important to track down what went wrong)\n\n" } // If we don't have an error it's really hard to make sense. if err == nil { w.WriteHeader(status) w.Write([]byte(msg)) return } if t, ok := err.(trace); ok { msg += "Trace:\n" msg += strings.Replace(string(t.t), "\n", "\n\t", -1) msg += "\n" err = t.e } if appengine.IsOverQuota(err) { msg += "Reason: Over Quota" } else if appengine.IsTimeoutError(err) { msg += "Reason: Timeout Error" } else { msg += fmt.Sprintf("Reason: %s", err) } w.WriteHeader(status) w.Write([]byte(msg)) }
func (g giImpl) IsOverQuota(err error) bool { return appengine.IsOverQuota(err) }