-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove string checking in API error handling
Use strongly typed errors to set HTTP status codes. Error interfaces are defined in the api/errors package and errors returned from controllers are checked against these interfaces. Errors can be wraeped in a pkg/errors.Causer, as long as somewhere in the line of causes one of the interfaces is implemented. The special error interfaces take precedence over Causer, meaning if both Causer and one of the new error interfaces are implemented, the Causer is not traversed. Signed-off-by: Brian Goff <[email protected]>
- Loading branch information
Showing
127 changed files
with
1,777 additions
and
871 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package errdefs | ||
|
||
// ErrNotFound signals that the requested object doesn't exist | ||
type ErrNotFound interface { | ||
NotFound() | ||
} | ||
|
||
// ErrInvalidParameter signals that the user input is invalid | ||
type ErrInvalidParameter interface { | ||
InvalidParameter() | ||
} | ||
|
||
// ErrConflict signals that some internal state conflicts with the requested action and can't be performed. | ||
// A change in state should be able to clear this error. | ||
type ErrConflict interface { | ||
Conflict() | ||
} | ||
|
||
// ErrUnauthorized is used to signify that the user is not authorized to perform a specific action | ||
type ErrUnauthorized interface { | ||
Unauthorized() | ||
} | ||
|
||
// ErrUnavailable signals that the requested action/subsystem is not available. | ||
type ErrUnavailable interface { | ||
Unavailable() | ||
} | ||
|
||
// ErrForbidden signals that the requested action cannot be performed under any circumstances. | ||
// When a ErrForbidden is returned, the caller should never retry the action. | ||
type ErrForbidden interface { | ||
Forbidden() | ||
} | ||
|
||
// ErrSystem signals that some internal error occurred. | ||
// An example of this would be a failed mount request. | ||
type ErrSystem interface { | ||
ErrSystem() | ||
} | ||
|
||
// ErrNotModified signals that an action can't be performed because it's already in the desired state | ||
type ErrNotModified interface { | ||
NotModified() | ||
} | ||
|
||
// ErrNotImplemented signals that the requested action/feature is not implemented on the system as configured. | ||
type ErrNotImplemented interface { | ||
NotImplemented() | ||
} | ||
|
||
// ErrUnknown signals that the kind of error that occurred is not known. | ||
type ErrUnknown interface { | ||
Unknown() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// Package errdefs defines a set of error interfaces that packages should use for communicating classes of errors. | ||
// Errors that cross the package boundary should implement one (and only one) of these interfaces. | ||
// | ||
// Packages should not reference these interfaces directly, only implement them. | ||
// To check if a particular error implements one of these interfaces, there are helper | ||
// functions provided (e.g. `Is<SomeError>`) which can be used rather than asserting the interfaces directly. | ||
// If you must assert on these interfaces, be sure to check the causal chain (`err.Cause()`). | ||
package errdefs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package errdefs | ||
|
||
type causer interface { | ||
Cause() error | ||
} | ||
|
||
func getImplementer(err error) error { | ||
switch e := err.(type) { | ||
case | ||
ErrNotFound, | ||
ErrInvalidParameter, | ||
ErrConflict, | ||
ErrUnauthorized, | ||
ErrUnavailable, | ||
ErrForbidden, | ||
ErrSystem, | ||
ErrNotModified, | ||
ErrNotImplemented, | ||
ErrUnknown: | ||
return e | ||
case causer: | ||
return getImplementer(e.Cause()) | ||
default: | ||
return err | ||
} | ||
} | ||
|
||
// IsNotFound returns if the passed in error is a ErrNotFound | ||
func IsNotFound(err error) bool { | ||
_, ok := getImplementer(err).(ErrNotFound) | ||
return ok | ||
} | ||
|
||
// IsInvalidParameter returns if the passed in error is an ErrInvalidParameter | ||
func IsInvalidParameter(err error) bool { | ||
_, ok := getImplementer(err).(ErrInvalidParameter) | ||
return ok | ||
} | ||
|
||
// IsConflict returns if the passed in error is a ErrConflict | ||
func IsConflict(err error) bool { | ||
_, ok := getImplementer(err).(ErrConflict) | ||
return ok | ||
} | ||
|
||
// IsUnauthorized returns if the the passed in error is an ErrUnauthorized | ||
func IsUnauthorized(err error) bool { | ||
_, ok := getImplementer(err).(ErrUnauthorized) | ||
return ok | ||
} | ||
|
||
// IsUnavailable returns if the passed in error is an ErrUnavailable | ||
func IsUnavailable(err error) bool { | ||
_, ok := getImplementer(err).(ErrUnavailable) | ||
return ok | ||
} | ||
|
||
// IsForbidden returns if the passed in error is a ErrForbidden | ||
func IsForbidden(err error) bool { | ||
_, ok := getImplementer(err).(ErrForbidden) | ||
return ok | ||
} | ||
|
||
// IsSystem returns if the passed in error is a ErrSystem | ||
func IsSystem(err error) bool { | ||
_, ok := getImplementer(err).(ErrSystem) | ||
return ok | ||
} | ||
|
||
// IsNotModified returns if the passed in error is a NotModified error | ||
func IsNotModified(err error) bool { | ||
_, ok := getImplementer(err).(ErrNotModified) | ||
return ok | ||
} | ||
|
||
// IsNotImplemented returns if the passed in error is a ErrNotImplemented | ||
func IsNotImplemented(err error) bool { | ||
_, ok := getImplementer(err).(ErrNotImplemented) | ||
return ok | ||
} | ||
|
||
// IsUnknown returns if the passed in error is an ErrUnknown | ||
func IsUnknown(err error) bool { | ||
_, ok := getImplementer(err).(ErrUnknown) | ||
return ok | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.