| Index: milo/common/error.go
|
| diff --git a/milo/common/error.go b/milo/common/error.go
|
| index 291e9a60fd7dd2e67b5a76573278821e4c2d29f2..b3e2e05869eba0c03530cb295cd542577772e12a 100644
|
| --- a/milo/common/error.go
|
| +++ b/milo/common/error.go
|
| @@ -15,16 +15,80 @@
|
| 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
|
| +// and grpc frontends know how to render the error in a way that will help the
|
| +// user.
|
| +type ErrorCode int
|
| +
|
| +const (
|
| + // CodeUnknown means an error happened, but we weren't able to classify it.
|
| + CodeUnknown ErrorCode = iota
|
| +
|
| + // CodeUnauthorized occurs when a user isn't logged in, but needs to be to
|
| + // proceed further.
|
| + CodeUnauthorized
|
| +
|
| + // CodeNoAccess occurs when the currently logged-in user is not permitted to
|
| + // see the resource.
|
| + 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")}
|
|
|