WithReportError handles error reporting. It should be placed after `WithMonitoring`, but before `WithPanic`.
(h RouteHandler)
| 92 | // WithReportError handles error reporting. |
| 93 | // It should be placed after `WithMonitoring`, but before `WithPanic`. |
| 94 | func (r *Router) WithReportError(h RouteHandler) RouteHandler { |
| 95 | return func(reqID string, rw ResponseWriter, req *http.Request) *Error { |
| 96 | // Open the error context |
| 97 | ctx := errorreport.StartRequest(req) |
| 98 | req = req.WithContext(ctx) |
| 99 | errorreport.SetMetadata(req, "Request ID", reqID) |
| 100 | |
| 101 | // Call the underlying handler passing the context downwards |
| 102 | err := h(reqID, rw, req) |
| 103 | if err == nil { |
| 104 | return nil |
| 105 | } |
| 106 | |
| 107 | // We do not need to send any canceled context |
| 108 | if !errors.Is(err.Err, context.Canceled) { |
| 109 | r.monitoring.SendError(ctx, err.Category, err.Err) |
| 110 | } |
| 111 | |
| 112 | // Report error to error collectors |
| 113 | if err.Err.ShouldReport() { |
| 114 | r.errorReporter.Report(err.Err, req) |
| 115 | } |
| 116 | |
| 117 | // Log response and format the error output |
| 118 | LogResponse(reqID, req, err.Err.StatusCode(), err.Err) |
| 119 | |
| 120 | // Error message: either is public message or full development error |
| 121 | if r.config.DevelopmentErrorsMode { |
| 122 | // Generate and serve HTML error page |
| 123 | html, contentType := generateErrorHTML(err.Err, reqID, req.Header) |
| 124 | |
| 125 | rw.Header().Set(httpheaders.ContentType, contentType) |
| 126 | rw.WriteHeader(err.Err.StatusCode()) |
| 127 | rw.Write(html) |
| 128 | |
| 129 | return nil |
| 130 | } |
| 131 | |
| 132 | rw.Header().Set(httpheaders.ContentType, "text/plain") |
| 133 | rw.WriteHeader(err.Err.StatusCode()) |
| 134 | rw.Write([]byte(err.Err.PublicMessage())) |
| 135 | |
| 136 | return nil |
| 137 | } |
| 138 | } |