errors.go 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package main
  2. import (
  3. "fmt"
  4. "runtime"
  5. "strings"
  6. )
  7. type imgproxyError struct {
  8. StatusCode int
  9. Message string
  10. PublicMessage string
  11. Unexpected bool
  12. stack []uintptr
  13. }
  14. func (e *imgproxyError) Error() string {
  15. return e.Message
  16. }
  17. func (e *imgproxyError) FormatStack() string {
  18. if e.stack == nil {
  19. return ""
  20. }
  21. return formatStack(e.stack)
  22. }
  23. func (e *imgproxyError) StackTrace() []uintptr {
  24. return e.stack
  25. }
  26. func (e *imgproxyError) SetUnexpected(u bool) *imgproxyError {
  27. e.Unexpected = u
  28. return e
  29. }
  30. func newError(status int, msg string, pub string) *imgproxyError {
  31. return &imgproxyError{
  32. StatusCode: status,
  33. Message: msg,
  34. PublicMessage: pub,
  35. }
  36. }
  37. func newUnexpectedError(msg string, skip int) *imgproxyError {
  38. return &imgproxyError{
  39. StatusCode: 500,
  40. Message: msg,
  41. PublicMessage: "Internal error",
  42. Unexpected: true,
  43. stack: callers(skip + 3),
  44. }
  45. }
  46. func callers(skip int) []uintptr {
  47. stack := make([]uintptr, 10)
  48. n := runtime.Callers(skip, stack)
  49. return stack[:n]
  50. }
  51. func formatStack(stack []uintptr) string {
  52. lines := make([]string, len(stack))
  53. for i, pc := range stack {
  54. f := runtime.FuncForPC(pc)
  55. file, line := f.FileLine(pc)
  56. lines[i] = fmt.Sprintf("%s:%d %s", file, line, f.Name())
  57. }
  58. return strings.Join(lines, "\n")
  59. }