forked from goadesign/goa
/
error_handler.go
49 lines (45 loc) · 1.62 KB
/
error_handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package middleware
import (
"net/http"
"github.com/goadesign/goa"
"golang.org/x/net/context"
)
// ErrorHandler turns a Go error into an HTTP response. It should be placed in the middleware chain
// below the logger middleware so the logger properly logs the HTTP response. ErrorHandler
// understands instances of goa.Error and returns the status and response body embodied in them,
// it turns other Go error types into a 500 internal error response.
// If verbose is false the details of internal errors is not included in HTTP responses.
func ErrorHandler(service *goa.Service, verbose bool) goa.Middleware {
return func(h goa.Handler) goa.Handler {
return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
e := h(ctx, rw, req)
if e == nil {
return nil
}
status := http.StatusInternalServerError
var respBody interface{}
if err, ok := e.(*goa.Error); ok {
status = err.Status
respBody = err
goa.ContextResponse(ctx).ErrorCode = err.Code
rw.Header().Set("Content-Type", goa.ErrorMediaIdentifier)
} else {
respBody = e.Error()
rw.Header().Set("Content-Type", "text/plain")
}
if status >= 500 && status < 600 {
reqID := ctx.Value(reqIDKey)
if reqID == nil {
reqID = shortID()
ctx = context.WithValue(ctx, reqIDKey, reqID)
}
goa.LogError(ctx, "uncaught error", "id", reqID, "msg", respBody)
if !verbose {
rw.Header().Set("Content-Type", goa.ErrorMediaIdentifier)
respBody = goa.ErrInternal("%s [%s]", http.StatusText(http.StatusInternalServerError), reqID)
}
}
return service.Send(ctx, status, respBody)
}
}
}