OLD | NEW |
1 // Copyright 2015 The LUCI Authors. | 1 // Copyright 2015 The LUCI Authors. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 package common | 15 package common |
16 | 16 |
17 import ( | 17 import ( |
18 » "github.com/luci/luci-go/server/router" | 18 » "net/http" |
19 » "github.com/luci/luci-go/server/templates" | 19 |
| 20 » "github.com/luci/luci-go/common/errors" |
20 ) | 21 ) |
21 | 22 |
22 // ErrorPage writes an error page into c.Writer with an http code "code" | 23 // ErrorCode represents milo's internal error code system. The subsystems in |
23 // and custom message. | 24 // milo can attach an ErrorCode to an error (using ErrorTag), and then the html |
24 func ErrorPage(c *router.Context, code int, message string) { | 25 // and grpc frontends know how to render the error in a way that will help the |
25 » c.Writer.WriteHeader(code) | 26 // user. |
26 » templates.MustRender(c.Context, c.Writer, "pages/error.html", templates.
Args{ | 27 type ErrorCode int |
27 » » "Code": code, | 28 |
28 » » "Message": message, | 29 const ( |
29 » }) | 30 » // CodeUnknown means an error happened, but we weren't able to classify
it. |
| 31 » CodeUnknown ErrorCode = iota |
| 32 |
| 33 » // CodeUnauthorized occurs when a user isn't logged in, but needs to be
to |
| 34 » // proceed further. |
| 35 » CodeUnauthorized |
| 36 |
| 37 » // CodeNoAccess occurs when the currently logged-in user is not permitte
d to |
| 38 » // see the resource. |
| 39 » CodeNoAccess |
| 40 |
| 41 » // CodeNotFound occurs when we weren't able to find the build that the |
| 42 » // user asked for. |
| 43 » CodeNotFound |
| 44 |
| 45 » // CodeParameterError occurs when one or more of the user-provided param
eters |
| 46 » // was malformed. |
| 47 » CodeParameterError |
| 48 ) |
| 49 |
| 50 var httpCode = map[ErrorCode]int{ |
| 51 » CodeUnauthorized: http.StatusUnauthorized, |
| 52 » CodeNoAccess: http.StatusForbidden, |
| 53 » CodeNotFound: http.StatusNotFound, |
| 54 » CodeParameterError: http.StatusBadRequest, |
30 } | 55 } |
| 56 |
| 57 // HTTPStatus returns an HTTP Status code corresponding to this ErrorCode. |
| 58 func (c ErrorCode) HTTPStatus() int { |
| 59 if ret, ok := httpCode[c]; ok { |
| 60 return ret |
| 61 } |
| 62 return http.StatusInternalServerError |
| 63 } |
| 64 |
| 65 // Tag returns an errors.TagValue for this code. |
| 66 func (c ErrorCode) Tag() errors.TagValue { |
| 67 return ErrorTag.With(c) |
| 68 } |
| 69 |
| 70 // GenerateErrorTagValue implements errors.TagValueGenerator so that ErrorCodes |
| 71 // can be used like: |
| 72 // errors.Annotate(err).Tag(CodeNotFound) |
| 73 // errors.New("terrible thing", CodeNotFound) |
| 74 func (c ErrorCode) GenerateErrorTagValue() errors.TagValue { |
| 75 return ErrorTag.With(c) |
| 76 } |
| 77 |
| 78 type errorTag struct{ Key errors.TagKey } |
| 79 |
| 80 func (t *errorTag) In(err error) ErrorCode { |
| 81 v, ok := errors.TagValueIn(t.Key, err) |
| 82 if ok { |
| 83 return v.(ErrorCode) |
| 84 } |
| 85 return CodeUnknown |
| 86 } |
| 87 |
| 88 func (t *errorTag) With(value ErrorCode) errors.TagValue { |
| 89 return errors.TagValue{Key: t.Key, Value: value} |
| 90 } |
| 91 |
| 92 // ErrorTag should be used to tag errors in the milo ecosystem to categorize |
| 93 // them so they can be rendered properly in the frontend. |
| 94 var ErrorTag = errorTag{errors.NewTagKey("holds a milo ErrorCode")} |
OLD | NEW |