Chromium Code Reviews| Index: milo/common/error.go |
| diff --git a/milo/common/error.go b/milo/common/error.go |
| index 291e9a60fd7dd2e67b5a76573278821e4c2d29f2..f7e6c749bf4b405fb6d465e84cd0f83dc27ee7f2 100644 |
| --- a/milo/common/error.go |
| +++ b/milo/common/error.go |
| @@ -15,16 +15,79 @@ |
| package common |
| import ( |
| - "github.com/luci/luci-go/server/router" |
| - "github.com/luci/luci-go/server/templates" |
| + "net/http" |
| + |
| + "github.com/luci/luci-go/common/errors" |
| +) |
| + |
| +// ErrorCode represents milo's internal error code system. The subsystems in |
| +// milo can attach an ErrorCode to an error (using ErrorTag), and then the |
| +// html frontends know how to render the error in a way that will help the user. |
|
Ryan Tseng
2017/07/13 22:00:46
html and grpc
iannucci
2017/07/14 19:00:23
Done.
|
| +type ErrorCode int |
| + |
| +const ( |
| + // CodeUnknown means an error happened, but we weren't able to classify it. |
| + CodeUnknown ErrorCode = iota |
| + |
| + // CodeUnauthorized occurs when the user may be able to see build, but they're |
|
Ryan Tseng
2017/07/13 22:00:47
but they weren't logged in...
iannucci
2017/07/14 19:00:23
Done.
|
| + // not logged in, so we don't know. |
| + CodeUnauthorized |
| + |
| + // CodeNoAccess occurs when the user is not able to see the build given the |
|
Ryan Tseng
2017/07/13 22:00:47
was not able to see... (I noticed the convention h
iannucci
2017/07/14 19:00:23
tweaked
|
| + // account that they're logged in as. |
| + CodeNoAccess |
| + |
| + // CodeNotFound occurs when we weren't able to find the build that the |
| + // user asked for. |
| + CodeNotFound |
| + |
| + // CodeParameterError occurs when one or more of the user-provided parameters |
| + // was malformed. |
| + CodeParameterError |
| ) |
| -// ErrorPage writes an error page into c.Writer with an http code "code" |
| -// and custom message. |
| -func ErrorPage(c *router.Context, code int, message string) { |
| - c.Writer.WriteHeader(code) |
| - templates.MustRender(c.Context, c.Writer, "pages/error.html", templates.Args{ |
| - "Code": code, |
| - "Message": message, |
| - }) |
| +var httpCode = map[ErrorCode]int{ |
| + CodeUnauthorized: http.StatusUnauthorized, |
| + CodeNoAccess: http.StatusForbidden, |
| + CodeNotFound: http.StatusNotFound, |
| + CodeParameterError: http.StatusBadRequest, |
| +} |
| + |
| +// HTTPStatus returns an HTTP Status code corresponding to this ErrorCode. |
| +func (c ErrorCode) HTTPStatus() int { |
| + if ret, ok := httpCode[c]; ok { |
| + return ret |
| + } |
| + return http.StatusInternalServerError |
| } |
| + |
| +// Tag returns an errors.TagValue for this code. |
| +func (c ErrorCode) Tag() errors.TagValue { |
| + return ErrorTag.With(c) |
| +} |
| + |
| +// GenerateErrorTagValue implements errors.TagValueGenerator so that ErrorCodes |
| +// can be used like: |
| +// errors.Annotate(err).Tag(CodeNotFound) |
| +// errors.New("terrible thing", CodeNotFound) |
| +func (c ErrorCode) GenerateErrorTagValue() errors.TagValue { |
| + return ErrorTag.With(c) |
| +} |
| + |
| +type errorTag struct{ Key errors.TagKey } |
| + |
| +func (t *errorTag) In(err error) ErrorCode { |
| + v, ok := errors.TagValueIn(t.Key, err) |
| + if ok { |
| + return v.(ErrorCode) |
| + } |
| + return CodeUnknown |
| +} |
| + |
| +func (t *errorTag) With(value ErrorCode) errors.TagValue { |
| + return errors.TagValue{Key: t.Key, Value: value} |
| +} |
| + |
| +// ErrorTag should be used to tag errors in the milo ecosystem to categorize |
| +// them so they can be rendered properly in the frontend. |
| +var ErrorTag = errorTag{errors.NewTagKey("holds a milo ErrorCode")} |