Skip to content

Commit bd0f8bb

Browse files
committed
chore: update error handling docs
1 parent 3342bf3 commit bd0f8bb

File tree

3 files changed

+86
-14
lines changed

3 files changed

+86
-14
lines changed

documentation/docs/guides/errors.md

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,85 @@ Error handling is a crucial part of any application. It is important to handle e
44

55
## Error handling in Fuego
66

7-
Fuego [controllers](./controllers) returns a value and an error. If the error is not `nil`, it means that an error occurred while processing the request. The error will be returned to the client as a JSON response.
7+
Fuego [controllers](./controllers) returns a value and an error. If the error is not `nil`,
8+
it means that an error occurred while processing the request.
9+
The error will be returned to the client as a JSON or XML response.
810

9-
By default, Fuego implements [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457), which defines a standard error format for HTTP APIs. We strongly recommend following this standard, but you can also use your own errors.
11+
The default error handler will transform any error that implements the
12+
`fuego.ErrorWithStatus` or `fuego.ErrorWithDetail` interfaces into a `fuego.HTTPError`. The `fuego.HTTPError` implements
13+
[RFC 9457](https://www.rfc-editor.org/rfc/rfc9457), which defines a standard error format for HTTP APIs.
14+
We strongly recommend following this standard, but you can also use your own errors.
1015

11-
The error type returned as JSON is `fuego.HTTPError`. It has a `Status` and a `Info` field. The `Status` field is an integer that represents the error code. The `Info` field is a string that contains a human-readable error message.
16+
The default `fuego.ErrorHandler` can be overridden using `fuego.WithErrorHandler` at fuego Server creation time.
1217

13-
If your error implements `Status() int` and `Info()` methods, the error will include the status code and the error message in the `fuego.HTTPError` response.
18+
The error type of `fuego.HTTPError` is returned as JSON or XML depending on the content-type specified.
19+
It's structure is the following:
20+
21+
```go
22+
// HTTPError is the error response used by the serialization part of the framework.
23+
type HTTPError struct {
24+
// Developer readable error message. Not shown to the user to avoid security leaks.
25+
Err error `json:"-" xml:"-"`
26+
// URL of the error type. Can be used to lookup the error in a documentation
27+
Type string `json:"type,omitempty" xml:"type,omitempty" description:"URL of the error type. Can be used to lookup the error in a documentation"`
28+
// Short title of the error
29+
Title string `json:"title,omitempty" xml:"title,omitempty" description:"Short title of the error"`
30+
// HTTP status code. If using a different type than [HTTPError], for example [BadRequestError],
31+
// this will be automatically overridden after Fuego error handling.
32+
Status int `json:"status,omitempty" xml:"status,omitempty" description:"HTTP status code" example:"403"`
33+
// Human readable error message
34+
Detail string `json:"detail,omitempty" xml:"detail,omitempty" description:"Human readable error message"`
35+
Instance string `json:"instance,omitempty" xml:"instance,omitempty"`
36+
Errors []ErrorItem `json:"errors,omitempty" xml:"errors,omitempty"`
37+
}
38+
```
39+
40+
If your error implements `fuego.ErrorWithStatus` or `fuego.ErrorWithDetail`
41+
the error will be returned as a `fuego.HTTPError`.
42+
43+
```go
44+
// ErrorWithStatus is an interface that can be implemented by an error to provide
45+
// a status code
46+
type ErrorWithStatus interface {
47+
error
48+
StatusCode() int
49+
}
50+
51+
// ErrorWithDetail is an interface that can be implemented by an error to provide
52+
// an additional detail message about the error
53+
type ErrorWithDetail interface {
54+
error
55+
DetailMsg() string
56+
}
57+
```
58+
59+
Example:
1460

1561
```go
1662
type MyCustomError struct {
17-
Status int
18-
Message string
63+
Err error `json:"error"`
64+
Message string `json:"message"`
65+
}
66+
67+
var _ fuego.ErrorWithStatus = MyCustomError{}
68+
var _ fuego.ErrorWithDetail = MyCustomError{}
69+
70+
func (e MyCustomError) Error() string { return e.Err.Error() }
71+
72+
func (e MyCustomError) StatusCode() int { return http.StatusTeapot }
73+
74+
func (e MyCustomError) DetailMsg() string {
75+
return strings.Split(e.Error(), " ")[1]
1976
}
77+
```
2078

21-
func (e MyCustomError) Status() int {
22-
return e.Status
79+
Alternatively, you can always use `fuego.HTTPError` directly such as:
80+
81+
```go
82+
err := fuego.HTTPError{
83+
Title: "unauthorized access",
84+
Detail: "wrong username or password",
85+
Status: http.StatusUnauthorized,
2386
}
2487
```
2588

@@ -33,3 +96,4 @@ Fuego provides a set of default errors that you can use in your application.
3396
- `fuego.NotFoundError`: 404 Not Found
3497
- `fuego.ConflictError`: 409 Conflict
3598
- `fuego.InternalServerError`: 500 Internal Server Error
99+
- `fuego.NotAcceptableError`: 406 Not Acceptable

errors.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,31 @@ import (
88
)
99

1010
// ErrorWithStatus is an interface that can be implemented by an error to provide
11-
// additional information about the error.
11+
// a status code
1212
type ErrorWithStatus interface {
1313
error
1414
StatusCode() int
1515
}
1616

17+
// ErrorWithDetail is an interface that can be implemented by an error to provide
18+
// an additional detail message about the error
1719
type ErrorWithDetail interface {
1820
error
1921
DetailMsg() string
2022
}
2123

2224
// HTTPError is the error response used by the serialization part of the framework.
2325
type HTTPError struct {
24-
Err error `json:"-" xml:"-"` // Developer readable error message. Not shown to the user to avoid security leaks.
25-
Type string `json:"type,omitempty" xml:"type,omitempty" description:"URL of the error type. Can be used to lookup the error in a documentation"` // URL of the error type. Can be used to lookup the error in a documentation
26-
Title string `json:"title,omitempty" xml:"title,omitempty" description:"Short title of the error"` // Short title of the error
27-
Status int `json:"status,omitempty" xml:"status,omitempty" description:"HTTP status code" example:"403"` // HTTP status code. If using a different type than [HTTPError], for example [BadRequestError], this will be automatically overridden after Fuego error handling.
28-
Detail string `json:"detail,omitempty" xml:"detail,omitempty" description:"Human readable error message"` // Human readable error message
26+
// Developer readable error message. Not shown to the user to avoid security leaks.
27+
Err error `json:"-" xml:"-"`
28+
// URL of the error type. Can be used to lookup the error in a documentation
29+
Type string `json:"type,omitempty" xml:"type,omitempty" description:"URL of the error type. Can be used to lookup the error in a documentation"`
30+
// Short title of the error
31+
Title string `json:"title,omitempty" xml:"title,omitempty" description:"Short title of the error"`
32+
// HTTP status code. If using a different type than [HTTPError], for example [BadRequestError], this will be automatically overridden after Fuego error handling.
33+
Status int `json:"status,omitempty" xml:"status,omitempty" description:"HTTP status code" example:"403"`
34+
// Human readable error message
35+
Detail string `json:"detail,omitempty" xml:"detail,omitempty" description:"Human readable error message"`
2936
Instance string `json:"instance,omitempty" xml:"instance,omitempty"`
3037
Errors []ErrorItem `json:"errors,omitempty" xml:"errors,omitempty"`
3138
}

server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ func WithErrorSerializer(serializer ErrorSender) func(*Server) {
370370
return func(c *Server) { c.SerializeError = serializer }
371371
}
372372

373+
// WithErrorHandler sets a customer error handler for the server
373374
func WithErrorHandler(errorHandler func(err error) error) func(*Server) {
374375
return func(c *Server) { c.ErrorHandler = errorHandler }
375376
}

0 commit comments

Comments
 (0)