fail

package module
v0.0.0-...-b4b74c7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 27, 2020 License: MIT Imports: 5 Imported by: 0

README

Fail GoDoc ghit.me Go Report Card

Manage and handle Go errors with nice and correct HTTP responses.

Fail allows to wrap errors and describe them as HTTP responses, such as, "Not Found" and "Bad Request" and their status code. Also, help you mask internal errors with friendly messages that are appropriate for clients.

The goal of this package is to handle the behavior of errors to minimize static errors and type assertions. If all errors are wrapped with fail.Cause we can inspect them better and give clients proper responses.

This package is inspired by Dave Cheney's excellent blog post "Don’t just check errors, handle them gracefully".

Quick Start

Install using "go get":

go get github.com/codehack/fail

Then import from your source:

import "github.com/codehack/fail"

Documentation

The documentation at GoDoc:

http://godoc.org/github.com/codehack/fail

Example

package main

import "github.com/codehack/fail"

// Create a new user, using JSON values.
http.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
	// we want a POST request, this will fail.
	if r.Method != "POST" {
		status, m := fail.Say(fail.BadRequest("request not POST"))
		http.Error(w, m, status)
		return
	}

	var payload struct {
		Name string        `json:"name"`
		Created *time.Time `json:"created"`
	}

	// JSON is hard, this will fail.
	if err := json.Decode(r.Request.Body, &payload); err != nil {
		var (
			m string
			status int
		)
		switch {
		case err == json.SyntaxError:
			status, m = fail.Say(fail.Cause(err).Unexpected())
		default:
			status, m = fail.Say(fail.Cause(err).BadRequest("your payload is terrible"))
		}
		http.Error(w, m, status)
		return
	}

	// if we manage to get this far, this will fail.
	if err := saveUserDB(&payload); err != nil {
		status, m := fail.Say(fail.Cause(err).Unexpected())
		http.Error(w, m, status)
		return
	}

	// Hah hah, this will fail.
	status, m := fail.Say(fail.Forbidden("resistance is futile."))
	http.Error(w, m, status)
})

Credits

Fail is Copyright (c) 2017 Codehack. Published under an MIT License

Documentation

Overview

Package fail is used to manage Go errors as HTTP responses. The goal is to respond to web clients nicely, and inspect errors.

To use fail, you must wrap Go errors using “fail.Cause“. This function will return a “Fail“ object that implements the “error“ interface. Also, the location of the original error is saved in the object for later inspection.

The “Fail“ object can be further handled with methods matching HTTP responses such as “fail.BadRequest“ and “fail.NotFound“.

Finally, to respond to a web client we use the “fail.Say“ function which returns the HTTP status code and message that can be sent via “http.Error“.

Index

Constants

View Source
const Version = "0.0.1"

Version is the version of this package.

Variables

View Source
var ErrUnspecified = fmt.Errorf("unspecified error")

ErrUnspecified is a fallback for fail without cause, or nil.

Functions

func BadRequest

func BadRequest(m string, fields ...string) error

BadRequest is a convenience function to return a Bad Request fail when there's no Go error.

func Forbidden

func Forbidden(m string) error

Forbidden is a convenience function to return a Forbidden fail when there's no Go error.

func IsBadRequest

func IsBadRequest(err error) bool

IsBadRequest returns true if fail is a Bad Request fail, false otherwise.

func IsForbidden

func IsForbidden(err error) bool

IsForbidden returns true if fail is a Forbidden fail, false otherwise.

func IsNotFound

func IsNotFound(err error) bool

IsNotFound returns true if fail is a Not Found fail, false otherwise.

func IsUnauthorized

func IsUnauthorized(err error) bool

IsUnauthorized returns true if fail is a Unauthorized fail, false otherwise.

func IsUnexpected

func IsUnexpected(err error) bool

IsUnexpected returns true if fail is an internal fail, false otherwise. This type of fail might be coming from an unhandled source.

func IsUnknown

func IsUnknown(err error) bool

IsUnknown returns true if the fail is not handled through this interface, false otheriwse.

func NotFound

func NotFound(m ...string) error

NotFound is a convenience function to return a Not Found fail when there's no Go error.

func Say

func Say(err error) (int, string)

Say returns the HTTP status and message response for a handled fail. If the error is nil, then there's no error -- say everything is OK. If the error is not a handled fail, then convert it to an unexpected fail.

func Unauthorized

func Unauthorized(m string) error

Unauthorized is a convenience function to return an Unauthorized fail when there's no Go error.

func Unexpected

func Unexpected() error

Unexpected is a convenience function to return an Internal Server Error fail when there's no Go error.

Types

type Fail

type Fail struct {
	Status  int      `json:"-"`
	Message string   `json:"message"`
	Details []string `json:"details,omitempty"`
	// contains filtered or unexported fields
}

Fail is an error that could be handled in an HTTP response. - Status: the HTTP Status code of the response (400-4XX, 500-5XX) - Message: friendly error message (for clients) - Details: slice of error details. e.g., form validation errors.

func Cause

func Cause(prev error) *Fail

Cause wraps an error into a Fail that could be linked to another.

func (*Fail) BadRequest

func (f *Fail) BadRequest(m string, details ...string) error

BadRequest changes the Go error to a "Bad Request" fail. `m` is the reason why this is a bad request. `details` is an optional slice of details to explain the fail.

func (*Fail) Caller

func (f *Fail) Caller(skip int)

Caller finds the file and line where the failure happened. `skip` is the number of calls to skip, not including this call. If you use this from a point(s) which is not the error location, then that call must be skipped.

func (*Fail) Error

func (f *Fail) Error() string

Error implements the error interface. Ideally, you don't want to send out this to web clients, this is meant to be used with logging and tools.

func (*Fail) Forbidden

func (f *Fail) Forbidden(m string) error

Forbidden changes an error to a "Forbidden" fail. `m` is the reason why this action is forbidden.

func (*Fail) Format

func (f *Fail) Format(s fmt.State, c rune)

Format implements the fmt.Formatter interface. This allows a Fail object to have Sprintf verbs for its values.

Verb	Description
----	---------------------------------------------------

%%  	Percent sign
%d		All fail details separated with commas (``Fail.Details``)
%e		The original error (``error.Error``)
%f		File name where the fail was called, minus the path.
%l		Line of the file for the fail
%m		The message of the fail (``Fail.Message``)
%s		HTTP Status code (``Fail.Status``)

Example:

// Print file, line, and original error.
// Note: we use index [1] to reuse `f` argument.
f := fail.Cause(err)
fmt.Printf("%[1]f:%[1]l %[1]e", f)
// Output:
// alerts.go:123 missing argument to vars

func (*Fail) NotFound

func (f *Fail) NotFound(m ...string) error

NotFound changes the error to an "Not Found" fail.

func (*Fail) String

func (f *Fail) String() string

String implements the fmt.Stringer interface, to make fails errors print nicely.

func (*Fail) Unauthorized

func (f *Fail) Unauthorized(m string) error

Unauthorized changes the error to an "Unauthorized" fail.

func (*Fail) Unexpected

func (f *Fail) Unexpected() error

Unexpected morphs the error into an "Internal Server Error" fail.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL