Error writes the error to the response writer.
(w http.ResponseWriter, r *http.Request, err error)
| 90 | |
| 91 | // Error writes the error to the response writer. |
| 92 | func Error(w http.ResponseWriter, r *http.Request, err error) { |
| 93 | code, err := ProcessError(err) |
| 94 | if code >= 500 && code != http.StatusNotImplemented { |
| 95 | errEvent := sentryerrors.NewEvent(err) |
| 96 | errEvent.Request = sentry.NewRequest(r) |
| 97 | if host, _, err := net.SplitHostPort(r.RemoteAddr); err == nil { |
| 98 | errEvent.User.IPAddress = host |
| 99 | } |
| 100 | for k, v := range errEvent.Request.Headers { |
| 101 | switch strings.ToLower(k) { |
| 102 | case "authorization": |
| 103 | parts := strings.SplitN(v, " ", 2) |
| 104 | if len(parts) == 2 && strings.ToLower(parts[0]) == "bearer" { |
| 105 | if tokenType, tokenID, _, err := auth.SplitToken(parts[1]); err == nil { |
| 106 | errEvent.Tags["auth.token_type"] = tokenType.String() |
| 107 | errEvent.Tags["auth.token_id"] = tokenID |
| 108 | } |
| 109 | } |
| 110 | delete(errEvent.Request.Headers, k) |
| 111 | case "cookie": |
| 112 | delete(errEvent.Request.Headers, k) |
| 113 | case "x-request-id": |
| 114 | errEvent.Tags["request_id"] = v |
| 115 | case "x-real-ip": |
| 116 | errEvent.User.IPAddress = v |
| 117 | } |
| 118 | } |
| 119 | sentry.CaptureEvent(errEvent) |
| 120 | } |
| 121 | if errPtr, ok := r.Context().Value(errorContextValue).(*error); ok && errPtr != nil { |
| 122 | *errPtr = err |
| 123 | } |
| 124 | |
| 125 | handlers, _ := r.Context().Value(errorHandlersKey).(map[string]http.Handler) |
| 126 | offers := append(make([]string, 0, len(handlers)+1), "application/json") |
| 127 | for k := range handlers { |
| 128 | offers = append(offers, k) |
| 129 | } |
| 130 | sort.Strings(offers) |
| 131 | |
| 132 | ct := httputil.NegotiateContentType(r, offers, "application/json") |
| 133 | w.Header().Set("Content-Type", ct) |
| 134 | w.WriteHeader(code) |
| 135 | switch ct { |
| 136 | case "application/json": |
| 137 | enc := json.NewEncoder(w) |
| 138 | enc.SetIndent("", "\t") |
| 139 | _ = enc.Encode(err) |
| 140 | default: |
| 141 | r := r.WithContext(context.WithValue(r.Context(), errorKey, err)) |
| 142 | handlers[ct].ServeHTTP(w, r) |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | // JSON encodes the provided message as JSON. When a marshalling error |
| 147 | // is encountered, Error is used in order to handle the error. |