errors.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package apierrors
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "github.com/porter-dev/porter/internal/logger"
  6. )
  7. type RequestError interface {
  8. Error() string
  9. ExternalError() string
  10. InternalError() string
  11. GetStatusCode() int
  12. }
  13. type ErrInternal struct {
  14. err error
  15. }
  16. func NewErrInternal(err error) RequestError {
  17. return &ErrInternal{err}
  18. }
  19. func (e *ErrInternal) Error() string {
  20. return e.err.Error()
  21. }
  22. func (e *ErrInternal) InternalError() string {
  23. return e.err.Error()
  24. }
  25. func (e *ErrInternal) ExternalError() string {
  26. return "An internal error occurred."
  27. }
  28. func (e *ErrInternal) GetStatusCode() int {
  29. return http.StatusInternalServerError
  30. }
  31. type ErrForbidden struct {
  32. err error
  33. }
  34. func NewErrForbidden(err error) RequestError {
  35. return &ErrForbidden{err}
  36. }
  37. func (e *ErrForbidden) Error() string {
  38. return e.err.Error()
  39. }
  40. func (e *ErrForbidden) InternalError() string {
  41. return e.err.Error()
  42. }
  43. func (e *ErrForbidden) ExternalError() string {
  44. return "Forbidden"
  45. }
  46. func (e *ErrForbidden) GetStatusCode() int {
  47. return http.StatusForbidden
  48. }
  49. // errors that should be passed directly, with no filter
  50. type ErrPassThroughToClient struct {
  51. err error
  52. statusCode int
  53. }
  54. func NewErrPassThroughToClient(err error, statusCode int) RequestError {
  55. return &ErrPassThroughToClient{err, statusCode}
  56. }
  57. func (e *ErrPassThroughToClient) Error() string {
  58. return e.err.Error()
  59. }
  60. func (e *ErrPassThroughToClient) InternalError() string {
  61. return e.err.Error()
  62. }
  63. func (e *ErrPassThroughToClient) ExternalError() string {
  64. return e.err.Error()
  65. }
  66. func (e *ErrPassThroughToClient) GetStatusCode() int {
  67. return e.statusCode
  68. }
  69. type externalError struct {
  70. Error string `json:"error"`
  71. }
  72. func HandleAPIError(
  73. w http.ResponseWriter,
  74. logger *logger.Logger,
  75. err RequestError,
  76. ) {
  77. extErrorStr := err.ExternalError()
  78. // log the internal error
  79. logger.Warn().
  80. Str("internal_error", err.InternalError()).
  81. Str("external_error", extErrorStr).
  82. Msg("")
  83. // send the external error
  84. resp := &externalError{extErrorStr}
  85. // write the status code
  86. w.WriteHeader(err.GetStatusCode())
  87. writerErr := json.NewEncoder(w).Encode(resp)
  88. if writerErr != nil {
  89. logger.Error().
  90. Err(writerErr).
  91. Msg("")
  92. }
  93. return
  94. }