problem

package module
v0.0.0-...-90fd743 Latest Latest
Warning

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

Go to latest
Published: Feb 22, 2025 License: MIT Imports: 9 Imported by: 0

README

problem-details
build-status go report license build-status Coverage Status build-status

ProblemDetails is a Error Handler base on RFC 7807 standard to map our error to standardized error payload to client. The data model for problem details is a JSON object; when formatted as a JSON document, it uses the application/problem+json media type and for XML format it uses the application/problem+xml media type. By defining machine-readable details of HTTP errors, we can avoid defining new error response formats for HTTP APIs.

Our problem details response body and headers will be look like this:

    // Response body

{
    "status": 400,                                        // The HTTP status code generated on the problem occurrence
    "title": "bad-request",                               // A short human-readable problem summary
    "detail": "We have a bad request in our endpoint",    // A human-readable explanation for what exactly happened
    "type": "https://httpstatuses.io/400",                // URI reference to identify the problem type
    "instance": "/sample1",                               // URI reference of the occurrence
    "stackTrace": "some more trace for error",            // More trace information error for what exactly happened
}
    // Response headers

     content-type: application/problem+json
     date: Thu,29 Sep 2022 14:07:23 GMT 

There are some samples for using this package on top of Echo here and for Gin here.

Installation

go get github.com/lazysmock/problem-details

Web-Frameworks

Echo

Error Handler:

For handling our error we need to specify an Error Handler on top of Echo framework:

// EchoErrorHandler middleware for handle problem details error on echo
func EchoErrorHandler(error error, c echo.Context) {

        // add custom map problem details here...

	// resolve problem details error from response in echo
	if !c.Response().Committed {
		if _, err := problem.ResolveProblemDetails(c.Response(), c.Request(), error); err != nil {
			log.Error(err)
		}
	}
}
Map Status Code Error:

In this sample we map status code StatusBadGateway to StatusUnauthorized base on handler config to problem details error.

// handle specific status code to problem details error
func sample1(c echo.Context) error {
       err := errors.New("We have a specific status code error in our endpoint")
       return echo.NewHTTPError(http.StatusBadGateway, err)
}
// problem details handler config
problem.MapStatus(http.StatusBadGateway, func() problem.ProblemDetailErr {
       return &problem.ProblemDetail{
           Status: http.StatusUnauthorized,
           Title:  "unauthorized",
           Detail: error.Error(),
       }
})
Map Custom Type Error:

In this sample we map custom error type to problem details error.

// handle custom type error to problem details error
func sample2(c echo.Context) error {
        err := errors.New("We have a custom type error in our endpoint")
	return custom_errors.BadRequestError{InternalError: err}
}
// problem details handler config
problem.Map[custom_errors.BadRequestError](func() problem.ProblemDetailErr {
       return &problem.ProblemDetail{
           Status: http.StatusBadRequest,
           Title:  "bad request",
           Detail: error.Error(),
       }
})

Gin

Error Handler:

For handling our error we need to specify an Error Handler on top of Gin framework:

// GinErrorHandler middleware for handle problem details error on gin
func GinErrorHandler() gin.HandlerFunc {
	return func(c *gin.Context) {

		c.Next()

		for _, err := range c.Errors {

                        // add custom map problem details here...
			
			if _, err := problem.ResolveProblemDetails(c.Writer, c.Request, err); err != nil {
				log.Error(err)
			}
		}
	}
}
Map Status Code Error:

In this sample we map status code StatusBadGateway to StatusUnauthorized base on handler config to problem details error.

// handle specific status code to problem details error
func sample1(c *gin.Context) {
       err := errors.New("We have a specific status code error in our endpoint")
       _ = c.AbortWithError(http.StatusBadGateway, err)
}
// problem details handler config
problem.MapStatus(http.StatusBadGateway, func() problem.ProblemDetailErr {
        return &problem.ProblemDetail{
            Status: http.StatusUnauthorized,
            Title:  "unauthorized",
            Detail: err.Error(),
        }
})
Map Custom Type Error:

In this sample we map custom error type to problem details error.

// handle custom type error to problem details error
func sample2(c *gin.Context) {
        err := errors.New("We have a custom type error in our endpoint")
	customBadRequestError := custom_errors.BadRequestError{InternalError: err}
	_ = c.Error(customBadRequestError)
}
// problem details handler config
problem.Map[custom_errors.BadRequestError](func() problem.ProblemDetailErr {
       return &problem.ProblemDetail{
           Status: http.StatusBadRequest,
           Title:  "bad request",
           Detail: err.Error(),
       }
})

Custom Problem Details:

We support custom problem details error for create more flexibility response error:

// custom problem details
type CustomProblemDetail struct {
            problem.ProblemDetailErr
	    Description    string `json:"description,omitempty"`
	    AdditionalInfo string `json:"additionalInfo,omitempty"`
}
// problem details handler config
problem.Map[custom_errors.ConflictError](func() problem.ProblemDetailErr {
       return &custom_problems.CustomProblemDetail{
           ProblemDetailErr: &problem.ProblemDetail{
               Status: http.StatusConflict,
               Title:  "conflict",
               Detail: error.Error(),
           },
           AdditionalInfo: "some additional info...",
           Description:    "some description...",
       }
})

Support

If you like my work, feel free to:

  • ⭐ this repository. And we will be happy together :)

Thanks a bunch for supporting me!

Contribution

Thanks to all contributors, you're awesome and this wouldn't be possible without you! The goal is to build a categorized community-driven collection of very well-known resources.

Please follow this contribution guideline to submit a pull request or create the issue.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var LFLEkoH = csGakp()

Functions

func Map

func Map[T error](funcProblem func() ProblemDetailErr)

Map map custom type error to problem details error

func MapStatus

func MapStatus(statusCode int, funcProblem func() ProblemDetailErr)

MapStatus map status code to problem details error

Types

type ProblemDetail

type ProblemDetail struct {
	Status     int    `json:"status,omitempty"`
	Title      string `json:"title,omitempty"`
	Detail     string `json:"detail,omitempty"`
	Type       string `json:"type,omitempty"`
	Instance   string `json:"instance,omitempty"`
	StackTrace string `json:"stackTrace,omitempty"`
}

func (*ProblemDetail) GetDetails

func (p *ProblemDetail) GetDetails() string

func (*ProblemDetail) GetInstance

func (p *ProblemDetail) GetInstance() string

func (*ProblemDetail) GetStackTrace

func (p *ProblemDetail) GetStackTrace() string

func (*ProblemDetail) GetStatus

func (p *ProblemDetail) GetStatus() int

func (*ProblemDetail) GetTitle

func (p *ProblemDetail) GetTitle() string

func (*ProblemDetail) GetType

func (p *ProblemDetail) GetType() string

func (*ProblemDetail) SetDetail

func (p *ProblemDetail) SetDetail(detail string) ProblemDetailErr

func (*ProblemDetail) SetInstance

func (p *ProblemDetail) SetInstance(instance string) ProblemDetailErr

func (*ProblemDetail) SetStackTrace

func (p *ProblemDetail) SetStackTrace(stackTrace string) ProblemDetailErr

func (*ProblemDetail) SetStatus

func (p *ProblemDetail) SetStatus(status int) ProblemDetailErr

func (*ProblemDetail) SetTitle

func (p *ProblemDetail) SetTitle(title string) ProblemDetailErr

func (*ProblemDetail) SetType

func (p *ProblemDetail) SetType(typ string) ProblemDetailErr

type ProblemDetailErr

type ProblemDetailErr interface {
	SetStatus(status int) ProblemDetailErr
	GetStatus() int
	SetTitle(title string) ProblemDetailErr
	GetTitle() string
	SetDetail(detail string) ProblemDetailErr
	GetDetails() string
	SetType(typ string) ProblemDetailErr
	GetType() string
	SetInstance(instance string) ProblemDetailErr
	GetInstance() string
	SetStackTrace(stackTrace string) ProblemDetailErr
	GetStackTrace() string
}

ProblemDetailErr ProblemDetail error interface

func ResolveProblemDetails

func ResolveProblemDetails(w http.ResponseWriter, r *http.Request, err error) (ProblemDetailErr, error)

ResolveProblemDetails retrieve and resolve error with format problem details error

Directories

Path Synopsis
samples

Jump to

Keyboard shortcuts

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