writeError writes Twirp errors in the response and triggers hooks.
(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks)
| 594 | |
| 595 | // writeError writes Twirp errors in the response and triggers hooks. |
| 596 | func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { |
| 597 | // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. |
| 598 | var twerr twirp.Error |
| 599 | if !errors.As(err, &twerr) { |
| 600 | twerr = twirp.InternalErrorWith(err) |
| 601 | } |
| 602 | |
| 603 | statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) |
| 604 | ctx = ctxsetters.WithStatusCode(ctx, statusCode) |
| 605 | ctx = callError(ctx, hooks, twerr) |
| 606 | |
| 607 | respBody := marshalErrorToJSON(twerr) |
| 608 | |
| 609 | resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON |
| 610 | resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) |
| 611 | resp.WriteHeader(statusCode) // set HTTP status code and send response |
| 612 | |
| 613 | _, writeErr := resp.Write(respBody) |
| 614 | if writeErr != nil { |
| 615 | // We have three options here. We could log the error, call the Error |
| 616 | // hook, or just silently ignore the error. |
| 617 | // |
| 618 | // Logging is unacceptable because we don't have a user-controlled |
| 619 | // logger; writing out to stderr without permission is too rude. |
| 620 | // |
| 621 | // Calling the Error hook would confuse users: it would mean the Error |
| 622 | // hook got called twice for one request, which is likely to lead to |
| 623 | // duplicated log messages and metrics, no matter how well we document |
| 624 | // the behavior. |
| 625 | // |
| 626 | // Silently ignoring the error is our least-bad option. It's highly |
| 627 | // likely that the connection is broken and the original 'err' says |
| 628 | // so anyway. |
| 629 | _ = writeErr |
| 630 | } |
| 631 | |
| 632 | callResponseSent(ctx, hooks) |
| 633 | } |
| 634 | |
| 635 | // sanitizeBaseURL parses the the baseURL, and adds the "http" scheme if needed. |
| 636 | // If the URL is unparsable, the baseURL is returned unchanged. |
no test coverage detected