srverrors

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: May 10, 2021 License: MIT Imports: 3 Imported by: 0

README

Srverrors

codecov Go Report Card

srverrors lets you create and serve HTTP errors with additional info such as ID of the HTTP request and error causes (error details). Each error has its own unqiue error code and user friendly message.
You can declare your own JSON error structure that will be returned in the HTTP response body or use the default one.
Errors for your service can be generated from the YAML file with errors definitions.

Table of Contents

Creating an error

Manually

An error can be created using srverrors.New or srverrors.NewWithErr functions, providing HTTP status code, error code and user friendly message. Creating an error with srverrors.NewWithErr allows you to pass original error.
Error code is unchangeable code of the error type from your service.

   if err := CheckAuth(token); err != nil {
        return srverrors.NewWithErr(http.StatusUnauthorized, "001-001", "Invalid token.", err)
   }
Declare an error type

HTTP services usually have a list of HTTP errors they respond with and this list should be provided in documentation of the service.

Creating errors of certain types manually, like in the example above, is not very convenient, so the best way to define a new type of the error in your service is to declare functions that return errors of certain types. A certain error type also can be declared as a struct with the `srverrors.Err` interface.

Declaring an error type:

   type InvalidParametersError struct {
	    srverrors.Err
    }

    func CreateInvalidParametersError() *InvalidParametersError {
	    srvErr := srverrors.New(http.StatusBadRequest, "002-567", "Invalid request parameters.")
	    return &InvalidParametersError{srvErr}
    }

    func (e *InvalidParametersError) AddInvalidEmail(email string) {
	    e.AddCause("email", email, "Invalid email address.")
    }

Creating an error in your code:

   if !isEmailValid(email) {
	    err := CreateInvalidParametersError()
	    err.AddInvalidEmail(email)
	    return err
   }
Generate error types from YAML

Error types can be declared in the YAML file and generated from it. To do so, install the generator:

go install github.com/Quanare/srverrors/srverrors-generator

Then create the source YAML file in the following format:

<Error type>:
  code: <Error code>
  message: <Error message>
  http_status_code: <Error HTTP status code>

And run the generator srverrors-generator -s <source file path> -o <result .go file path> -p <name of the result file's package>.

You can check example source YAML file and result of the generation from that file. Command to generate the example:

srverrors-generator -s ./srverrors-generator/test-data/source.yaml -o ./srverrors-generator/test-data/expected_result.go -p test_data

Serving an error

srverrors.Presenter allows you to write an HTTP error response in the format you want.
If you don't define your own format, the default format is used. The default format is declared with srverrors.DefaultErrView and srverrors.DefaultCauseView.

Example of the default format:

{
    "error":{
        "code": "022-044",
        "message": "User is not allowed to see the application."
    },
    "request_id": "c3057227-feb5-4b64-b0fd-dfb83714c7df",
    "causes":
    [
        {
            "param": "role",
            "value": "guest",
            "message": "Invalid role."
        }
    ]
}
Writing an HTTP response

To write an error response, use Presenter.WriteJSONResponse.

Custom JSON error structure

To define your own format, do the following:

  1. Implement srverrors.ErrView and srverrors.CauseView.
     type CustomViewErr struct {
         ErrorCode    string                `json:"error_code"`
         ErrorMessage string                `json:"error_message"`
         RequestID    string                `json:"id,omitempty"`
         Causes       []srverrors.CauseView `json:"details,omitempty"`
     }
    
     func (ev *CustomViewErr) SetCode(code string) {
         ev.ErrorCode = code
     }
    
     func (ev *CustomViewErr) SetMessage(message string) {
         ev.ErrorMessage = message
     }
    
     func (ev *CustomViewErr) SetRequestID(requestID string) {
         ev.RequestID = requestID
     }
    
     func (ev *CustomViewErr) SetCauses(causes []srverrors.CauseView) {
         ev.Causes = causes
     }
    
     type CustomViewCause struct {
         Type         string `json:"type"`
         Value        string `json:"value"`
         ErrorMessage string `json:"error_message"`
     }
    
     func (cv *CustomViewCause) SetParam(paramType string) {
         cv.Type = paramType
     }
    
     func (cv *CustomViewCause) SetValue(value string) {
         cv.Value = value
     }
    
     func (cv *CustomViewCause) SetMessage(message string) {
         cv.ErrorMessage = message
     }
    
  2. Create a Presenter with PresenterConfig filled with functions that returns empty instances of your implementations.
    p := srverrors.CreatePresenter(srverrors.PresenterConfig{
             GetErrView: func() srverrors.ErrView {
                 return &CustomViewErr{}
             },
             GetCauseView: func() srverrors.CauseView {
                 return &CustomViewCause{}
             },
    })
    

With this example, the response body would be:

 {
    "error_code":"022-044",
    "error_message":"User is not allowed to see the application.",
    "id":"c3057227-feb5-4b64-b0fd-dfb83714c7df",
    "details":[
       {
          "type":"role",
          "value":"guest",
          "error_message":"Invalid role."
       }
    ]
 }

Documentation

Index

Constants

This section is empty.

Variables

View Source
var GetDefaultCauseView = func() CauseView {
	return &DefaultCauseView{}
}

GetDefaultCauseView provides function to create an empty instance of DefaultCauseView.

View Source
var GetDefaultErrView = func() ErrView {
	return &DefaultErrView{}
}

GetDefaultErrView provides function to create an empty instance of DefaultErrView.

Functions

This section is empty.

Types

type Cause

type Cause interface {
	// Param returns param name of the error cause.
	Param() string
	// Value returns param value of the error cause.
	Value() string
	// Message returns user friendly error cause message.
	Message() string
}

Cause encapsulates an HTTP error causes and details.

type CauseView

type CauseView interface {
	SetParam(param string)
	SetValue(value string)
	SetMessage(message string)
}

CauseView allows to define the error cause format used in the body of the HTTP response. The default CauseView implementation is DefaultCauseView.

type DefaultCauseView

type DefaultCauseView struct {
	Param   string `json:"param,omitempty"`
	Value   string `json:"value,omitempty"`
	Message string `json:"message,omitempty"`
}

DefaultCauseView is a default implementation of CauseView.

Example of the default format:

{
	"param":"role",
	"value":"guest",
	"message":"Invalid role."
}

func (*DefaultCauseView) SetMessage

func (cv *DefaultCauseView) SetMessage(message string)

SetMessage sets the cause message to the view.

func (*DefaultCauseView) SetParam

func (cv *DefaultCauseView) SetParam(param string)

SetParam sets the cause param name to the view.

func (*DefaultCauseView) SetValue

func (cv *DefaultCauseView) SetValue(value string)

SetValue sets the cause param value to the view.

type DefaultErrView

type DefaultErrView struct {
	Error struct {
		Code    string `json:"code"`
		Message string `json:"message"`
	} `json:"error"`
	RequestID string      `json:"request_id,omitempty"`
	Causes    []CauseView `json:"causes,omitempty"`
}

DefaultErrView is a default implementation of ErrView.

Example of the default format:

{
	"error":{
		"code":	"022-044",
		"message":	"User is not allowed to see the application."
	},
	"request_id":	"c3057227-feb5-4b64-b0fd-dfb83714c7df",
	"causes":
	[
		{
			"param":	"role",
			"value":	"guest",
			"message":	"Invalid role."
		}
	]
}

func (*DefaultErrView) SetCauses

func (ev *DefaultErrView) SetCauses(causes []CauseView)

SetCauses sets error causes to the view.

func (*DefaultErrView) SetCode

func (ev *DefaultErrView) SetCode(code string)

SetCode sets the error code to the view.

func (*DefaultErrView) SetMessage

func (ev *DefaultErrView) SetMessage(message string)

SetMessage sets the error message to the view.

func (*DefaultErrView) SetRequestID

func (ev *DefaultErrView) SetRequestID(requestID string)

SetRequestID sets the request ID to the view.

type Err

type Err interface {
	error
	// HTTPStatusCode returns status code that a HTTP handler should return.
	HTTPStatusCode() int
	// Code returns unique error code.
	Code() string
	// Message returns user friendly error message.
	Message() string
	// RequestID returns ID of the HTTP request.
	RequestID() string
	// Causes returns error's causes and details.
	Causes() []Cause
	// SetRequestID sets ID of the HTTP request.
	SetRequestID(requestID string)
	// AddCause adds cause or detail to the error.
	AddCause(param, value, message string)
}

Err encapsulates an error returned by an HTTP service.

func New

func New(httpCode int, code, message string) Err

New creates an Err with HTTP status code, error code and error message.

func NewWithErr

func NewWithErr(httpCode int, code, message string, source error) Err

NewWithErr creates an Err with HTTP status code, error code, error message and source error.

type ErrView

type ErrView interface {
	SetCode(code string)
	SetMessage(message string)
	SetRequestID(requestID string)
	SetCauses(causes []CauseView)
}

ErrView allows to define the error format used in the body of the HTTP response. The default ErrView implementation is DefaultErrView.

type GetCauseView

type GetCauseView func() CauseView

GetCauseView is a function to create an empty instance of CauseView.

type GetErrView

type GetErrView func() ErrView

GetErrView is a function to create an empty instance of ErrView.

type Presenter

type Presenter struct {
	// contains filtered or unexported fields
}

Presenter helps to handle errors and return an HTTP Response.

func CreatePresenter

func CreatePresenter(config PresenterConfig) Presenter

CreatePresenter creates a new Presenter using the given configuration. If some configuration parameters are not specified, the default values are used.

func (Presenter) ErrToJSON

func (p Presenter) ErrToJSON(err Err, w io.Writer) error

ErrToJSON marshalls the error to JSON using ErrView and CauseView formats.

func (Presenter) WriteJSONResponse

func (p Presenter) WriteJSONResponse(err Err, w http.ResponseWriter) error

WriteJSONResponse writes the HTTP error to ResponseWriter using ErrView and CauseView formats.

type PresenterConfig

type PresenterConfig struct {
	// GetErrView is a function to create an empty instance of ErrView.
	// To use custom error format, implement ErrView and pass a function that creates an empty instance of that imlementation.
	// The default value is GetDefaultErrView.
	GetErrView GetErrView

	// GetCauseView is a function to create an empty instance of CauseView.
	// To use custom cause format, implement CauseView and pass a function that creates an empty instance of that imlementation.
	// The default value is GetDefaultCauseView.
	GetCauseView GetCauseView
}

PresenterConfig is used to pass configuration options to Presenter's constructor.

Directories

Path Synopsis
test-data
Do not edit.
Do not edit.

Jump to

Keyboard shortcuts

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