blunder

package module
v0.0.7 Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2023 License: MIT Imports: 12 Imported by: 5

README

blunder

GoDoc Build GoReport Coverage Status

Package blunder is an error handling library with readable stack traces and flexible formatting support.

go get github.com/georgi-georgiev/blunder

Install

go install github.com/georgi-georgiev/blunder/cmd/blunder@latest

Run blunder gen in the project's root folder which contains the main.go file. This will parse your comments and generate the required files blunder.html.

Swagger

When you use swagger you need to add --parseVendor becuase searching in vendor folder is disabled by default e.g. swag init --parseVendor

Contributing

If you'd like to contribute to blunder, we'd love your input! Please submit an issue first so we can discuss your proposal.


Released under the MIT License.

Documentation

Index

Constants

View Source
const Version = "v0.0.7"

Variables

View Source
var ReasonGroups map[int]ReasonGroup = map[int]ReasonGroup{
	http.StatusBadRequest: {
		Status:      http.StatusBadRequest,
		Title:       "REQUEST_VALIDATION_FAILURE",
		Description: "The request failed because it contained an invalid value or missing required value. The value could be a parameter value, a header value, or a property value.",
		Resolution:  "Please correct the request as per the error description/details provided in the error response.",
	},
	http.StatusUnauthorized: {
		Status:      http.StatusUnauthorized,
		Title:       "UNAUTHORIZED",
		Description: "The user does not have valid authentication credentials for the target resource.",
		Resolution:  "Check the value of the Authorization HTTP request header.",
	},
	http.StatusForbidden: {
		Status:      http.StatusForbidden,
		Title:       "FORBIDDEN OR ACCESS_DENIED",
		Description: "The requested operation is forbidden and cannot be completed. This may be due to the user not having the necessary permissions for a resource or needing an account of some sort, or attempting a prohibited action (for example, deleting the client or device).",
		Resolution:  "Please ensure that access has been granted to the current user.",
	},
}
View Source
var Reasons map[ReasonCode]Reason = map[ReasonCode]Reason{
	BAD_CONTENT: {
		Message:     "The content type of the request data or the content type of a part of a multipart request is not supported.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
	},
	CORS_REQUEST_WITH_XORIGIN: {
		Message:     "The CORS request contains an XD3 X-Origin header, which is indicative of a bad CORS request.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
	},
	ENDPOINT_CONSTRAINT_MISMATCH: {
		Message:     "The request failed because it did not match the specified API.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
		Tip:         "Check the value of the URL path to make sure it is correct.",
	},
	INVALID: {
		Message:     "The request failed because it contained an invalid value.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
		Tip:         "The value could be a parameter value, a header value, or a property value.",
	},
	INVALID_HEADER: {
		Message:     "The request failed because it contained an invalid header.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
	},
	INVALID_PARAMETER: {
		Message:     "The request failed because it contained an invalid parameter or parameter value.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
	},
	INVALID_QUERY: {
		Message:     "The request failed because it contained an invalid value.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
	},
	KEY_EXPIRED: {
		Message:     "The API key provided in the request expired, which means the API server is unable to check the quota limit for the application making the request.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
		Tip:         "Check the for more information or to obtain a new key.",
	},
	KEY_INVALID: {
		Message:     "The API key provided in the request expired, which means the API server is unable to check the quota limit for the application making the request.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
		Tip:         "Check the for more information or to obtain a new key.",
	},
	NOT_DOWNLOAD: {
		Message:     "The request failed because it is not an download request.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
		Tip:         "Resend the request to the same path.",
	},
	NOT_UPLOAD: {
		Message:     "The request failed because it is not an upload request.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
		Tip:         "Resend the request to the same path.",
	},
	PARSE_ERROR: {
		Message:     "The API server cannot parse the request body.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
	},
	REQUIRED: {
		Message:     "The API request is missing required information.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
		Tip:         "The required information could be a parameter or resource property.",
	},
	TOO_MANY_PARTS: {
		Message:     "The multipart request failed because it contains too many parts.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
	},
	UNKNOWN_API: {
		Message:     "The client is using an unsupported media protocol.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
	},
	UNSUPPORTED_MEDIA_PROTOCOL: {
		Message:     "The client is using an unsupported media protocol.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
	},
	UNSUPPORTED_OUTPUT_FORMAT: {
		Message:     "The alt parameter value specifies an output format that is not supported for this service.",
		ReasonGroup: ReasonGroups[http.StatusBadRequest],
		Tip:         "Check the value of the alt request parameter.",
	},
	AUTHORIZATION_ERROR: {
		Message:     "The user is not authorized to make the request.",
		ReasonGroup: ReasonGroups[http.StatusUnauthorized],
	},
	EXPIRED: {
		Message:     "Session Expired.",
		ReasonGroup: ReasonGroups[http.StatusUnauthorized],
	},
	AUTH_REQUIRED: {
		Message:     "The user must be logged in to make this API request",
		ReasonGroup: ReasonGroups[http.StatusUnauthorized],
	},
	ACCESS_NOT_CONFIGURED: {
		Message:     "The project has been blocked due to abuse.",
		ReasonGroup: ReasonGroups[http.StatusForbidden],
	},
	ACCOUNT_DELETED: {
		Message:     "The user account associated with the request's authorization credentials has been deleted.",
		ReasonGroup: ReasonGroups[http.StatusForbidden],
	},
	ACCOUNT_DISABLED: {
		Message:     "The user account associated with the request's authorization credentials has been disabled.",
		ReasonGroup: ReasonGroups[http.StatusForbidden],
	},
	ACCOUNT_UNVERIFIED: {
		Message:     "The email address for the user making the request has not been verified.",
		ReasonGroup: ReasonGroups[http.StatusForbidden],
	},
	CONCURRENT_LIMIT_EXCEEDED: {
		Message:     "The request failed because a concurrent usage limit has been reached.",
		ReasonGroup: ReasonGroups[http.StatusForbidden],
	},
	DAILY_LIMIT_EXCEEDED: {
		Message:     "A daily quota limit for the API has been reached.",
		ReasonGroup: ReasonGroups[http.StatusForbidden],
	},
	INSUFFICIENT_AUTHORIZED_PARTY: {
		Message:     "The request cannot be completed for this application.",
		ReasonGroup: ReasonGroups[http.StatusForbidden],
	},
	LIMIT_EXCEEDED: {
		Message:     "The request cannot be completed due to access or rate limitations.",
		ReasonGroup: ReasonGroups[http.StatusForbidden],
	},
	QUOTA_EXCEEDED: {
		Message:     "The requested operation requires more resources than the quota allows.",
		ReasonGroup: ReasonGroups[http.StatusForbidden],
	},
	RATE_LIMIT_EXCEEDED: {
		Message:     "Too many requests have been sent within a given time span.",
		ReasonGroup: ReasonGroups[http.StatusForbidden],
	},
	RESPONSE_TOO_LARGE: {
		Message:     "The requested resource is too large to return.",
		ReasonGroup: ReasonGroups[http.StatusForbidden],
	},
	SERVING_LIMIT_EXCEEDED: {
		Message:     "The overall rate limit specified for the API has already been reached.",
		ReasonGroup: ReasonGroups[http.StatusForbidden],
	},
	SLL_REQUIRED: {
		Message:     "SSL is required to perform this operation.",
		ReasonGroup: ReasonGroups[http.StatusForbidden],
	},
	USER_RATE_LIMIT_EXCEEDED: {
		Message:     "The request failed because a per-user rate limit has been reached.",
		ReasonGroup: ReasonGroups[http.StatusForbidden],
	},
}

Functions

func Extend

func Extend(typeURI string, title string, status int)

func FromError

func FromError(err error) []validationError

Types

type Blunder

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

func New

func New() *Blunder

func NewRFC

func NewRFC() *Blunder

Note that both "type" and "instance" accept relative URIs; this means that they must be resolved relative to the document's base URI, as per [RFC3986], Section 5.

func NewWithOptions

func NewWithOptions(options BlunderOptions) *Blunder

func (*Blunder) Add

func (b *Blunder) Add(r *http.Request, err error)

func (*Blunder) AddCustomerError

func (b *Blunder) AddCustomerError(customerError CustomError)

func (*Blunder) BindJson

func (b *Blunder) BindJson(r *http.Request, payload interface{}) []validationError

func (*Blunder) Enrich

func (b *Blunder) Enrich(httpErr HTTPError) HTTPError

func (*Blunder) ErrorHandler

func (b *Blunder) ErrorHandler(logger *zap.Logger) Middleware

func (*Blunder) FromValidator

func (b *Blunder) FromValidator(errs validator.ValidationErrors, locale string) []validationError

func (*Blunder) Get

func (b *Blunder) Get(r *http.Request) []error

func (*Blunder) GinAdd

func (b *Blunder) GinAdd(c *gin.Context, err error)

func (*Blunder) GinErrorHandler

func (b *Blunder) GinErrorHandler(logger *zap.Logger) gin.HandlerFunc

func (*Blunder) GinGet

func (b *Blunder) GinGet(c *gin.Context) []error

func (*Blunder) GinNoMethod

func (b *Blunder) GinNoMethod(c *gin.Context)

func (*Blunder) GinNoRoute

func (b *Blunder) GinNoRoute(c *gin.Context)

func (*Blunder) GinRecovery

func (b *Blunder) GinRecovery(c *gin.Context, err any)

func (*Blunder) HandleErrors

func (b *Blunder) HandleErrors(r *http.Request, errs []error) (int, HTTPErrorResponse, bool)

func (*Blunder) Html

func (b *Blunder) Html(c *gin.Context)

func (*Blunder) RegisterCustomTranslation

func (b *Blunder) RegisterCustomTranslation(tag string, trans ut.Translator, registerFn validator.RegisterTranslationsFunc, translationFn validator.TranslationFunc) error

func (*Blunder) RegisterCustomValidation

func (b *Blunder) RegisterCustomValidation(tag string, fn validator.Func, callValidationEvenIfNull ...bool) error

func (*Blunder) SetEnvironment

func (b *Blunder) SetEnvironment(environment Environment)

type BlunderOptions

type BlunderOptions struct {
	Environment    Environment //stacktrace
	TypeURI        string
	Domain         string
	IsTraceable    bool //traceid,correlationid
	IsIdentifiable bool //include
	IsTimeable     bool //timestamp
	IsRecovarable  bool //recoverable, action
}

type CustomError

type CustomError interface {
	DefaultError
	ShouldAbort() bool
	Code() int
	WithTitle() string
	Recovarable() bool
}

type Data

type Data struct {
	ErrorCodes []ErrorCode
}

type DefaultError

type DefaultError interface {
	error
	ToHTPPError() HTTPError
}

type Environment

type Environment int
const (
	Development Environment = 0
	Test        Environment = 1
	Production  Environment = 2
)

type ErrorCode

type ErrorCode struct {
	Status      string
	Title       string
	Description string
	Resolution  string
	Code        int
	Reason      string
	Message     string
	Tip         string
}

type HTTPError

type HTTPError struct {

	//(string) A URI reference [RFC3986] that identifies the
	//problem type.  This specification encourages that, when
	//dereferenced, it provide human-readable documentation for the
	//problem type (e.g., using HTML [W3C.REC-html5-20141028]).  When
	//this member is not present, its value is assumed to be
	//"about:blank".
	Type string `json:"type,omitempty" message:"https://example.com/problems/request-parameters-missing"`

	//(strinrg) A short, human-readable summary of the problem
	//type.  It SHOULD NOT change from occurrence to occurrence of the
	//problem, except for purposes of localization (e.g., using
	//proactive content negotiation; see [RFC7231], Section 3.4).
	Title string `json:"title,omitempty" example:"required parameters are missing"`

	//(string) A human-readable explanation specific to this occurrence of the problem.
	Detail string `json:"detail,omitempty" example:"The parameters: limit, date were not provided"`

	ReasonCode int    `json:"reason_code,omitempty" example:"150"`
	Reason     string `json:"reason,omitempty" example:"invalidParameter"`

	Placement  string `json:"placement,omitempty" example:"field"`
	Field      string `json:"field,omitempty" example:"email"`
	Expression string `json:"expression,omitempty" example:"greater"` //greater, not equals, equals, min, max, required, etc.
	Argument   string `json:"argument,omitempty" example:"number"`    //number, string

	Action string `` /* 150-byte string literal not displayed */

	StackTrace string `json:"stack_trace,omitempty" example:"asda"`
}

A problem details object can have the following members:

func (HTTPError) Error

func (e HTTPError) Error() string

type HTTPErrorResponse

type HTTPErrorResponse struct {
	Errors []HTTPError `json:"errors"`

	//(number) The HTTP status code ([RFC7231], Section 6) generated by the origin server for this occurrence of the problem.
	Status int `json:"status,omitempty" example:"400"`

	//(strinrg) A URI reference that identifies the specificoccurrence of the problem.
	//It may or may not yield further information if dereferenced.
	Instance string `json:"instance,omitempty" example:"/login/log/abc123"`

	Language    string `json:"language,omitempty" example:"en"`
	Domain      string `json:"domain,omitempty" example:"global"`
	Timestamp   int    `json:"timestamp,omitempty" example:"1692604569"`
	Recoverable bool   `json:"recoverable,omitempty" example:"true"`

	TraceId       string `json:"trace_id,omitempty" example:"EJplcsCHuLu"`
	CorrelationId string `json:"correlation_id,omitempty" example:"asdas"`
}

func BadRequest

func BadRequest() HTTPErrorResponse

func Forbidden added in v0.0.2

func Forbidden() HTTPErrorResponse

func FromHTTPError

func FromHTTPError(status int, errs ...HTTPError) HTTPErrorResponse

func InternalServerError

func InternalServerError() HTTPErrorResponse

func MethodNotAllowed

func MethodNotAllowed() HTTPErrorResponse

func NewHTTPErrorResponse

func NewHTTPErrorResponse(status int, message string) HTTPErrorResponse

func NotFound

func NotFound() HTTPErrorResponse

func NotImpemented

func NotImpemented() HTTPErrorResponse

func ServiceUnavailable

func ServiceUnavailable() HTTPErrorResponse

func Unauthorized added in v0.0.4

func Unauthorized() HTTPErrorResponse

func (HTTPErrorResponse) ToJson

func (r HTTPErrorResponse) ToJson() []byte

func (HTTPErrorResponse) WithCorrelation

func (r HTTPErrorResponse) WithCorrelation(id string) HTTPErrorResponse

func (HTTPErrorResponse) WithDomain

func (r HTTPErrorResponse) WithDomain(domain string) HTTPErrorResponse

func (HTTPErrorResponse) WithInstance

func (r HTTPErrorResponse) WithInstance(instance string) HTTPErrorResponse

func (HTTPErrorResponse) WithLanguage

func (r HTTPErrorResponse) WithLanguage(language string) HTTPErrorResponse

func (HTTPErrorResponse) WithStatus

func (r HTTPErrorResponse) WithStatus(status int) HTTPErrorResponse

func (HTTPErrorResponse) WithTimestamp

func (r HTTPErrorResponse) WithTimestamp() HTTPErrorResponse

func (HTTPErrorResponse) WithTrace

func (r HTTPErrorResponse) WithTrace() HTTPErrorResponse

type Logger

type Logger interface {
	Error(err error)
}

type Middleware

type Middleware func(http.HandlerFunc) http.HandlerFunc

type Reason

type Reason struct {
	ReasonGroup ReasonGroup
	Message     string
	Tip         string
}

type ReasonCode

type ReasonCode int
const (
	CORS_REQUEST_WITH_XORIGIN     ReasonCode = 110
	ENDPOINT_CONSTRAINT_MISMATCH  ReasonCode = 120
	INVALID                       ReasonCode = 130
	BAD_CONTENT                   ReasonCode = 100
	INVALID_HEADER                ReasonCode = 140
	INVALID_PARAMETER             ReasonCode = 150
	INVALID_QUERY                 ReasonCode = 160
	KEY_EXPIRED                   ReasonCode = 170
	KEY_INVALID                   ReasonCode = 180
	NOT_DOWNLOAD                  ReasonCode = 190
	NOT_UPLOAD                    ReasonCode = 200
	PARSE_ERROR                   ReasonCode = 210
	REQUIRED                      ReasonCode = 220
	TOO_MANY_PARTS                ReasonCode = 230
	UNKNOWN_API                   ReasonCode = 240
	UNSUPPORTED_MEDIA_PROTOCOL    ReasonCode = 250
	UNSUPPORTED_OUTPUT_FORMAT     ReasonCode = 260
	AUTHORIZATION_ERROR           ReasonCode = 300
	EXPIRED                       ReasonCode = 310
	AUTH_REQUIRED                 ReasonCode = 320
	ACCOUNT_DELETED               ReasonCode = 410
	ACCOUNT_DISABLED              ReasonCode = 420
	ACCOUNT_UNVERIFIED            ReasonCode = 430
	ACCESS_NOT_CONFIGURED         ReasonCode = 400
	CONCURRENT_LIMIT_EXCEEDED     ReasonCode = 440
	DAILY_LIMIT_EXCEEDED          ReasonCode = 450
	INSUFFICIENT_AUTHORIZED_PARTY ReasonCode = 460
	LIMIT_EXCEEDED                ReasonCode = 470
	QUOTA_EXCEEDED                ReasonCode = 480
	RATE_LIMIT_EXCEEDED           ReasonCode = 490
	RESPONSE_TOO_LARGE            ReasonCode = 500
	SERVING_LIMIT_EXCEEDED        ReasonCode = 510
	SLL_REQUIRED                  ReasonCode = 520
	USER_RATE_LIMIT_EXCEEDED      ReasonCode = 530
)

func (ReasonCode) String

func (reasonCode ReasonCode) String() string

type ReasonGroup

type ReasonGroup struct {
	Status      int
	Title       string
	Description string
	Resolution  string
}

type RecordNotFoundError

type RecordNotFoundError struct {
	Name       string
	Identifier string
}

func (RecordNotFoundError) Code

func (e RecordNotFoundError) Code() int

func (RecordNotFoundError) Error

func (e RecordNotFoundError) Error() string

func (RecordNotFoundError) Recovarable

func (e RecordNotFoundError) Recovarable() bool

func (RecordNotFoundError) ShouldAbort

func (e RecordNotFoundError) ShouldAbort() bool

func (RecordNotFoundError) ToHTPPError

func (e RecordNotFoundError) ToHTPPError() HTTPError

func (RecordNotFoundError) WithTitle

func (e RecordNotFoundError) WithTitle() string

type ResourceAlreadyExistsError

type ResourceAlreadyExistsError struct {
	Name       string
	Identifier string
}

func (ResourceAlreadyExistsError) Code

func (ResourceAlreadyExistsError) Error

func (ResourceAlreadyExistsError) ShouldAbort

func (e ResourceAlreadyExistsError) ShouldAbort() bool

func (ResourceAlreadyExistsError) ToHTPPError

func (e ResourceAlreadyExistsError) ToHTPPError() HTTPError

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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