blob: b3e2e05869eba0c03530cb295cd542577772e12a [file] [log] [blame]
// Copyright 2015 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package common
import (
"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
)
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")}