Documentation ¶
Overview ¶
Package errs is a modified copy of the upspin.io/errors package. Originally, I used quite a bit of the upspin.io/errors package, but have moved to only use a very small amount of it. Even still, I think it's appropriate to leave the license information in...
Copyright 2016 The Upspin Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. Package errs defines the error handling used by all Upspin software.
Index ¶
- func E(args ...interface{}) error
- func HTTPErrorResponse(w http.ResponseWriter, lgr zerolog.Logger, err error)
- func KindIs(kind Kind, err error) bool
- func Match(err1, err2 error) bool
- func MatchUnauthenticated(err1, err2 error) bool
- type Code
- type ErrResponse
- type Error
- type InputUnwanted
- type Kind
- type MissingField
- type Parameter
- type ServiceError
- type UnauthenticatedError
- type UnauthorizedError
- type UserName
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func E ¶
func E(args ...interface{}) error
E builds an error value from its arguments. There must be at least one argument or E panics. The type of each argument determines its meaning. If more than one argument of a given type is presented, only the last one is recorded.
The types are:
UserName The username of the user attempting the operation. string Treated as an error message and assigned to the Err field after a call to errors.New. errors.Kind The class of error, such as permission failure. error The underlying error that triggered this one.
If the error is printed, only those items that have been set to non-zero values will appear in the result.
If Kind is not specified or Other, we set it to the Kind of the underlying error.
Example ¶
package main import ( "fmt" "github.com/pkg/errors" "github.com/gilcrest/httplog/errs" ) func main() { err := layer4() if err != nil { fmt.Println(err.Error()) } } func layer4() error { err := layer3() return err } func layer3() error { err := layer2() return err } func layer2() error { err := layer1() return err } func layer1() error { return errs.E(errs.Validation, errs.Parameter("testParam"), errs.Code("0212"), errors.New("Actual error message")) }
Output: Actual error message
func HTTPErrorResponse ¶
func HTTPErrorResponse(w http.ResponseWriter, lgr zerolog.Logger, err error)
HTTPErrorResponse takes a writer, error and a logger, performs a type switch to determine if the type is an Error (which meets the Error interface as defined in this package), then sends the Error as a response to the client. If the type does not meet the Error interface as defined in this package, then a proper error is still formed and sent to the client, however, the Kind and Code will be Unanticipated. Logging of error is also done using https://github.com/rs/zerolog
Example ¶
package main import ( "fmt" "net/http/httptest" "os" "github.com/rs/zerolog" "github.com/pkg/errors" "github.com/gilcrest/httplog/errs" "github.com/gilcrest/httplog/logger" ) func main() { w := httptest.NewRecorder() l := logger.NewLogger(os.Stdout, zerolog.DebugLevel, false) err := layer4() errs.HTTPErrorResponse(w, l, err) fmt.Println(w.Body) } func layer4() error { err := layer3() return err } func layer3() error { err := layer2() return err } func layer2() error { err := layer1() return err } func layer1() error { return errs.E(errs.Validation, errs.Parameter("testParam"), errs.Code("0212"), errors.New("Actual error message")) }
Output: {"level":"error","error":"Actual error message","http_statuscode":400,"Kind":"input_validation_error","Parameter":"testParam","Code":"0212","severity":"ERROR","message":"Error Response Sent"} {"error":{"kind":"input_validation_error","code":"0212","param":"testParam","message":"Actual error message"}}
func KindIs ¶
KindIs reports whether err is an *Error of the given Kind. If err is nil then KindIs returns false.
func Match ¶
Match compares its two error arguments. It can be used to check for expected errors in tests. Both arguments must have underlying type *Error or Match will return false. Otherwise it returns true if every non-zero element of the first error is equal to the corresponding element of the second. If the Err field is a *Error, Match recurs on that field; otherwise it compares the strings returned by the Error methods. Elements that are in the second argument but not present in the first are ignored.
For example,
Match(errors.E(upspin.UserName("joe@schmoe.com"), errors.Permission), err) tests whether err is an Error with Kind=Permission and User=joe@schmoe.com.
Example ¶
package main import ( "fmt" "github.com/pkg/errors" "github.com/gilcrest/httplog/errs" ) func main() { user := errs.UserName("joe@blow.com") err := errors.New("network unreachable") // Construct an error, one we pretend to have received from a test. got := errs.E(user, errs.IO, err) // Now construct a reference error, which might not have all // the fields of the error from the test. expect := errs.E(user, errs.IO, err) fmt.Println("Match:", errs.Match(expect, got)) // Now one that's incorrect - wrong Kind. got = errs.E(user, errs.Database, err) fmt.Println("Mismatch:", errs.Match(expect, got)) }
Output: Match: true Mismatch: false
func MatchUnauthenticated ¶
MatchUnauthenticated compares its two error arguments. It can be used to check for expected errors in tests. Both arguments must have underlying type *UnauthenticatedError or MatchUnauthenticated will return false. Otherwise it returns true if every non-zero element of the first error is equal to the corresponding element of the second. If the Err field is a *UnauthenticatedError, MatchUnauthenticated recurs on that field; otherwise it compares the strings returned by the Error methods. Elements that are in the second argument but not present in the first are ignored.
Types ¶
type ErrResponse ¶
type ErrResponse struct {
Error ServiceError `json:"error"`
}
ErrResponse is used as the Response Body
type Error ¶
type Error struct { // User is the username of the user attempting the operation. User UserName // Kind is the class of error, such as permission failure, // or "Other" if its class is unknown or irrelevant. Kind Kind // Param represents the parameter related to the error. Param Parameter // Code is a human-readable, short representation of the error Code Code // The underlying error that triggered this one, if any. Err error }
Error is the type that implements the error interface. It contains a number of fields, each of different type. An Error value may leave some values unset.
Example ¶
package main import ( "fmt" "github.com/gilcrest/httplog/errs" ) func main() { user := errs.UserName("joe@blow.com") // Single error. e1 := errs.E(errs.IO, "network unreachable") fmt.Println("\nSimple error:") fmt.Println(e1) // Nested error. fmt.Println("\nNested error:") e2 := errs.E(user, errs.Other, e1) fmt.Println(e2) }
Output: Simple error: network unreachable Nested error: network unreachable
type InputUnwanted ¶
type InputUnwanted string
InputUnwanted is an error type that can be used when validating input fields that have a value, but should should not
func (InputUnwanted) Error ¶
func (e InputUnwanted) Error() string
type Kind ¶
type Kind uint8
Kind defines the kind of error this is, mostly for use by systems such as FUSE that must act differently depending on the error.
const ( Other Kind = iota // Unclassified error. This value is not printed in the error message. Invalid // Invalid operation for this type of item. IO // External I/O error such as network failure. Exist // Item already exists. NotExist // Item does not exist. Private // Information withheld. Internal // Internal error or inconsistency. BrokenLink // Link target does not exist. Database // Error from database. Validation // Input validation error. Unanticipated // Unanticipated error. InvalidRequest // Invalid Request )
Kinds of errors.
The values of the error kinds are common between both clients and servers. Do not reorder this list or remove any items since that will change their values. New items must be added only to the end.
type MissingField ¶
type MissingField string
MissingField is an error type that can be used when validating input fields that do not have a value, but should
func (MissingField) Error ¶
func (e MissingField) Error() string
type ServiceError ¶
type ServiceError struct { Kind string `json:"kind,omitempty"` Code string `json:"code,omitempty"` Param string `json:"param,omitempty"` Message string `json:"message,omitempty"` }
ServiceError has fields for Service errors. All fields with no data will be omitted
type UnauthenticatedError ¶
type UnauthenticatedError struct { // WWWAuthenticateRealm is a description of the protected area. // If no realm is specified, "DefaultRealm" will be used as realm WWWAuthenticateRealm string // The underlying error that triggered this one, if any. Err error }
UnauthenticatedError implements the error interface and is used when a request lacks valid authentication credentials.
For Unauthenticated and Unauthorized errors, the response body should be empty. Use logger to log the error and then just send http.StatusUnauthorized (401).
From stack overflow - https://stackoverflow.com/questions/3297048/403-forbidden-vs-401-unauthorized-http-responses "In summary, a 401 Unauthorized response should be used for missing or bad authentication, and a 403 Forbidden response should be used afterwards, when the user is authenticated but isn’t authorized to perform the requested operation on the given resource."
func NewUnauthenticatedError ¶
func NewUnauthenticatedError(realm string, err error) *UnauthenticatedError
NewUnauthenticatedError is an initializer for UnauthenticatedError
func (UnauthenticatedError) Error ¶
func (e UnauthenticatedError) Error() string
func (UnauthenticatedError) Realm ¶
func (e UnauthenticatedError) Realm() string
Realm returns the WWWAuthenticateRealm of the error, if empty, Realm returns "DefaultRealm"
func (UnauthenticatedError) Unwrap ¶
func (e UnauthenticatedError) Unwrap() error
Unwrap method allows for unwrapping errors using errors.As
type UnauthorizedError ¶
type UnauthorizedError struct { error }Err
UnauthorizedError implements the error interface and is used when a user is authenticated, but is not authorized to access the resource.
For Unauthenticated and Unauthorized errors, the response body should be empty. Use logger to log the error and then just send http.StatusUnauthorized (401).
From stack overflow - https://stackoverflow.com/questions/3297048/403-forbidden-vs-401-unauthorized-http-responses "In summary, a 401 Unauthorized response should be used for missing or bad authentication, and a 403 Forbidden response should be used afterwards, when the user is authenticated but isn’t authorized to perform the requested operation on the given resource."
func NewUnauthorizedError ¶
func NewUnauthorizedError(err error) *UnauthorizedError
NewUnauthorizedError is an initializer for UnauthorizedError
func (UnauthorizedError) Error ¶
func (e UnauthorizedError) Error() string
func (UnauthorizedError) Unwrap ¶
func (e UnauthorizedError) Unwrap() error
Unwrap method allows for unwrapping errors using errors.As