xerrorz

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: May 4, 2019 License: Apache-2.0 Imports: 3 Imported by: 0

README

xerrorz

xerrorz provides GCP-like pretty formatted http error responses and also nested error logs powered by xerrors.

Supported F/W

xerrorz has helper functions specialized for several web frameworks

Error Contents

You can pick up from preset errors for top-level http error contents (HTTPErrDoc). See ErrType

type HTTPErr struct {
	ErrDoc HTTPErrDoc `json:"error"`
}

type HTTPErrDoc struct {
	Errors  []*InnerErr `json:"errors"`
	Code    int         `json:"code"`
	Message string      `json:"message"`
}

type InnerErr struct {
	Domain       string `json:"domain"`       // global, {yourServiceName}, usage,...
	Reason       string `json:"reason"`       // invalidParameter, required,...
	Location     string `json:"location"`     // Authorization, {paramName},...
	LocationType string `json:"locationType"` // header, parameter, requestBody,...
	Message      string `json:"message"`      // {description}
	Cause        error  `json:"-"`            // For internal-use error reporting, NOT included in error jsons
}
{
  "error": {
    "errors": [
      {
        "domain": "fooService",
        "reason": "invalidArgument",
        "location": "id",
        "locationType": "requestBody",
        "message": "Passed id is invalid"
      }
    ],
    "code": 400,
    "message": "Invalid argument"
  }
}

Usage

Example scenario: io.ErrClosedPipe causes invalidArgument.id and io.ErrNoProgress causes invalidArgument.name

import (
	"github.com/amaya382/xerrorz"
	"encoding/json"
	"fmt"
	"io" // For illustration
	"golang.org/x/xerrors"
)

// Example nested errors causing `invalidArgument.id`
e1 := xerrors.Errorf("e1: %w", io.ErrClosedPipe) // Original error
e2 := xerrors.Errorf("e2: %w", e1)               // Propagated once
e3 := xerrors.Errorf("e3: %w", e2)               // Propagated twice

errRes := xerrorz.NewHTTPErr(xerrorz.InvalidArgument,
	xerrorz.NewInnerErr("fooService", "invalidArgument", "id", "requestBody", "Passed id is invalid", e3),
	xerrorz.NewInnerErr("fooService", "invalidArgument", "name", "requestBody", "Passed name is invalid",
		io.ErrNoProgress))
bJSON, _ := json.Marshal(errRes)
fmt.Println(string(bJSON))  // (1) Print json
fmt.Printf("%+v\n", errRes) // (2) Print error for logging
(1) Generated Response JSON
{
  "error": {
    "errors": [
      {
        "domain": "fooService",
        "reason": "invalidArgument",
        "location": "id",
        "locationType": "requestBody",
        "message": "Passed id is invalid"
      },
      {
        "domain": "fooService",
        "reason": "invalidArgument",
        "location": "name",
        "locationType": "requestBody",
        "message": "Passed name is invalid"
      }
    ],
    "code": 400,
    "message": "Invalid argument"
  }
}
(2) Nested and Detailed Error Log powered by xerrors
[HTTP Status 400] Invalid argument:
    github.com/amaya382/xerrorz.TestJSONEquality0
        /home/amaya/work/xerrorz/xerrorz_test.go:41
  - Invalid argument:
    github.com/amaya382/xerrorz.NewHTTPErr
        /home/amaya/work/xerrorz/xerrorz.go:103
  - Passed id is invalid:
    github.com/amaya382/xerrorz.TestJSONEquality0
        /home/amaya/work/xerrorz/xerrorz_test.go:42
  - e3:
    github.com/amaya382/xerrorz.TestJSONEquality0
        /home/amaya/work/xerrorz/xerrorz_test.go:40
  - e2:
    github.com/amaya382/xerrorz.TestJSONEquality0
        /home/amaya/work/xerrorz/xerrorz_test.go:39
  - e1:
    github.com/amaya382/xerrorz.TestJSONEquality0
        /home/amaya/work/xerrorz/xerrorz_test.go:38
  - io: read/write on closed pipe:
  - Passed name is invalid:
    github.com/amaya382/xerrorz.TestJSONEquality0
        /home/amaya/work/xerrorz/xerrorz_test.go:43
  - multiple Read calls return no data or error

Usage for gin

Helper functions set a status code, a content-type header, and a body.

import (
	"github.com/amaya382/xerrorz"
	"github.com/amaya382/xerrorz/helper/xgin"
	"github.com/gin-gonic/gin"
	"io" // For illustration
)

	var c *gin.Context // Use a context from handlers

  // Status Code: 400
  // Header: Content-Type:application/json
  // Body: {error json}
	xgin.SetHTTPErrJSON(c, xerrorz.InvalidArgument,
		xerrorz.NewInnerErr("fooService", "invalidArgument", "id", "requestBody", "Passed id is invalid", nil),
		xerrorz.NewInnerErr("fooService", "invalidArgument", "name", "requestBody", "Passed name is invalid",
			io.ErrNoProgress))

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ErrQueue

type ErrQueue struct {
	Curr  error // Not ErrQueue
	Queue []*error
}

ErrQueue is a helper struct for allowing xerrors to go along well with tree-structured errors

func NewErrQueue

func NewErrQueue(
	curr error,
	queue []*error) *ErrQueue

func (ErrQueue) Error

func (e ErrQueue) Error() string

func (ErrQueue) Format

func (e ErrQueue) Format(s fmt.State, v rune)

func (ErrQueue) FormatError

func (e ErrQueue) FormatError(p xerrors.Printer) error

func (ErrQueue) Unwrap

func (e ErrQueue) Unwrap() error

type ErrType

type ErrType uint

Based on https://cloud.google.com/storage/docs/json_api/v1/status-codes#http-status-and-error-codes

const (
	// 400
	BadRequest ErrType = iota
	InvalidAltVaule
	InvalidArgument
	InvalidParameter
	ParseError
	Required
	TurnedDown

	// 401
	AuthenticationError
	NotAuthenticated
	NotAuthorized

	// 403
	AccountDisabled
	CountryBlocked
	Forbidden
	InsufficientPermissions
	SSLRequired

	// 404
	NotFound

	// 405
	MethodNotAllowed

	// 409
	Conflict

	// 410
	Gone

	// 411
	LengthRequired

	// 412
	ConditionNotMet

	// 413
	PayloadTooLarge

	// 416
	RequestedRangeNotSatisfiable

	// 429
	RateLimitExceeded
	UserRateLimitExceeded

	// 500
	InternalServerError

	// 502
	BadGateway

	// 503
	ServiceUnavailable
)

type HTTPErr

type HTTPErr struct {
	ErrDoc HTTPErrDoc `json:"error"`
	// contains filtered or unexported fields
}

func NewHTTPErr

func NewHTTPErr(errType ErrType, innerErrs ...*InnerErr) *HTTPErr

func (HTTPErr) Error

func (e HTTPErr) Error() string

func (HTTPErr) Format

func (e HTTPErr) Format(s fmt.State, v rune)

func (HTTPErr) FormatError

func (e HTTPErr) FormatError(p xerrors.Printer) error

func (HTTPErr) Unwrap

func (e HTTPErr) Unwrap() error

type HTTPErrDoc

type HTTPErrDoc struct {
	Errors  []*InnerErr `json:"errors"`
	Code    int         `json:"code" example:"429"`
	Message string      `json:"message" example:"Rate Limit Exceeded"`
	// contains filtered or unexported fields
}

func (HTTPErrDoc) Error

func (e HTTPErrDoc) Error() string

func (HTTPErrDoc) Format

func (e HTTPErrDoc) Format(s fmt.State, v rune)

func (HTTPErrDoc) FormatError

func (e HTTPErrDoc) FormatError(p xerrors.Printer) error

func (HTTPErrDoc) Unwrap

func (e HTTPErrDoc) Unwrap() error

type InnerErr

type InnerErr struct {
	Domain       string `json:"domain" example:"usage"`                // global, {yourService}, usage,...
	Reason       string `json:"reason" example:"rateLimitExceeded"`    // invalidParameter, required,...
	Location     string `json:"location" example:""`                   // Authorization, {paramName},...
	LocationType string `json:"locationType" example:""`               // header, parameter,...
	Message      string `json:"message" example:"Rate Limit Exceeded"` // {description}
	Cause        error  `json:"-"`                                     // For error reporting
	// contains filtered or unexported fields
}

func NewInnerErr

func NewInnerErr(domain string, reason string, location string,
	locationType string, message string, cause error) *InnerErr

func (InnerErr) Error

func (e InnerErr) Error() string

func (InnerErr) Format

func (e InnerErr) Format(s fmt.State, v rune)

func (InnerErr) FormatError

func (e InnerErr) FormatError(p xerrors.Printer) error

func (InnerErr) Unwrap

func (e InnerErr) Unwrap() error

Directories

Path Synopsis
helper

Jump to

Keyboard shortcuts

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