Introducing the Uerrors Package
Internal error messages are usually brief and in a format that is optimized for logging and searching.
An example would be:
> error=true, service=phantom, txid=12345, msg="user not authorized"
While that’s a great error message for developers to search by tags, its not a great error message to display to an end user.
Usually, there’s a translation layer that would take this error message and then return a more user friendly message to the end user. It might look something like:
switch err:
case ErrInvalidUser:
umsg := "You are not authorized to perform this action"
default:
umsg := err.Error()
// send umsg down in a response body along with an appropriate statsCode
It’s often hard to find all the code paths and errors an API request could create and then individually, add them to a swtich statement.
This is where uerrors comes in. It offers an easy interface to attach a user-friendly message while creating the original error itself.
Usage
To create a New uerror
err := uerrors.New("pkg: invalid token", "Please renew your API token")
To create an uerror with values available only at run time:
err := uerrors.FromErrors(fmt.Errorf("pkg: txnid=%s, resource=%s", txnid,resource),
fmt.Errorf("Your API request to %s failed. Please contact support if the issue persists", resource))
Constructing an user friendly response:
package main
import (
"fmt"
"io"
"log"
"net/http"
"github.com/joshi4/uerrors"
)
func main() {
http.HandleFunc("/feature", serveFeature)
http.HandleFunc("/", serveIndex)
http.ListenAndServe(":6060", nil)
}
func serveIndex(w http.ResponseWriter, req *http.Request) {
uerr := uerrors.New("example: redirect failed", "Please visit http://localhost:6060/feature if you aren't redirected automatically")
log.Println(uerr.Error())
io.WriteString(w, uerr.UserError())
}
func serveFeature(w http.ResponseWriter, req *http.Request) {
path := req.URL.Path
uerr := uerrors.FromErrors(fmt.Errorf("example: error=true, endpoint=%s", path),
fmt.Errorf("Please visit %s a little later", path))
log.Println(uerr.Error())
io.WriteString(w, uerr.UserError())
}