Skip to content

A go library that implements application/problem+json and application/problem+xml

License

Notifications You must be signed in to change notification settings

mschneider82/problem

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

problem

Coverage PkgGoDev Go Report Card

A golang library that implements application/problem+json and application/problem+xml

Features

  • compatible with application/problem+json
  • inspired by https://github.com/zalando/problem
  • RFC link https://tools.ietf.org/html/rfc7807
  • a Problem implements the Error interface and can be compared with errors.Is()
  • Wrap an error to a Problem
  • application/problem+xml is also supported using xml.Unmarshal and xml.Marshal
  • Auto-Title based on StatusCode with problem.Of(statusCode)

Install

go get -u schneider.vip/problem

Usage

problem.New(problem.Title("Not Found"), problem.Status(404)).JSONString()

Will produce this:

{
  "status": 404,
  "title": "Not Found"
}

You can also autofill the title based on the StatusCode:

problem.Of(404)

Will produce the same problem as above!

You can also append some more options:

p := problem.Of(http.StatusNotFound)
p.Append(problem.Detail("some more details"))

// Use the Marshaler interface to get the problem json as []byte
jsonBytes, err := json.Marshal(p)

// or simpler (ignores the error)
jsonBytes = p.JSON()

Custom key/values are also supported:

problem.New(problem.Title("Not Found"), problem.Custom("key", "value"))

To write the Problem directly to a http.ResponseWriter:

http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	problem.New(
		problem.Type("https://example.com/404"),
		problem.Status(404),
	).WriteTo(w)
})

Create a Problem from an existing error

_, err := ioutil.ReadFile("non-existing")
if err != nil {
	p := problem.New(
		problem.Wrap(err),
		problem.Title("Internal Error"),
		problem.Status(404),
	)
	if !errors.Is(p, os.ErrNotExist) {
		t.Fatalf("expected not existing error")
	}
}

Gin Framework

If you are using gin you can simply reply the problem to the client:

func(c *gin.Context) {
	problem.New(
		problem.Title("houston! we have a problem"),
		problem.Status(http.StatusNotFound),
	).WriteTo(c.Writer)
}

Echo Framework

If you are using echo you can use the following error handler to handle Problems and return them to client.

func ProblemHandler(err error, c echo.Context) {
	if prb, ok := err.(*problem.Problem); ok {
		if !c.Response().Committed {
			if c.Request().Method == http.MethodHead {
				prb.WriteHeaderTo(c.Response())
			} else if _, err := prb.WriteTo(c.Response()); err != nil {
				c.Logger().Error(err)
			}
		}
	} else {
		c.Echo().DefaultHTTPErrorHandler(err, c)
	}
}

...
// e is an instance of echo.Echo
e.HTTPErrorHandler = ProblemHandler

About

A go library that implements application/problem+json and application/problem+xml

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages