180 lines
2.7 KiB
Go
180 lines
2.7 KiB
Go
package response
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"ruben/inventory2/internal/consts"
|
|
"strings"
|
|
)
|
|
|
|
type (
|
|
// ErrorResponse is an error
|
|
ErrorResponse struct {
|
|
err error
|
|
msg string
|
|
status int
|
|
html []byte
|
|
}
|
|
)
|
|
|
|
// Constructors
|
|
|
|
func Errorf(format string, args ...any) ErrorResponse {
|
|
return ErrorResponse{
|
|
err: fmt.Errorf(format, args...),
|
|
}
|
|
}
|
|
|
|
func BadRequest() ErrorResponse {
|
|
return ErrorResponse{
|
|
status: http.StatusBadRequest,
|
|
}
|
|
}
|
|
|
|
func NotFound() ErrorResponse {
|
|
return ErrorResponse{
|
|
status: http.StatusNotFound,
|
|
}
|
|
}
|
|
|
|
func Unauthorized() ErrorResponse {
|
|
return ErrorResponse{
|
|
status: http.StatusUnauthorized,
|
|
}
|
|
}
|
|
|
|
func Forbidden() ErrorResponse {
|
|
return ErrorResponse{
|
|
status: http.StatusForbidden,
|
|
}
|
|
}
|
|
|
|
func Conflict() ErrorResponse {
|
|
return ErrorResponse{
|
|
status: http.StatusConflict,
|
|
}
|
|
}
|
|
|
|
// builder pattern implementation
|
|
|
|
func (e ErrorResponse) Msg(msg string) ErrorResponse {
|
|
e.msg = msg
|
|
return e
|
|
}
|
|
|
|
func (e ErrorResponse) Msgf(format string, args ...any) ErrorResponse {
|
|
e.msg = fmt.Sprintf(format, args...)
|
|
return e
|
|
}
|
|
|
|
func (e ErrorResponse) Status(status int) ErrorResponse {
|
|
e.status = status
|
|
return e
|
|
}
|
|
|
|
func (e ErrorResponse) Wrap(err error) ErrorResponse {
|
|
e.err = err
|
|
return e
|
|
}
|
|
|
|
func (e ErrorResponse) HTML(h []byte) ErrorResponse {
|
|
e.html = h
|
|
return e
|
|
}
|
|
|
|
// error implementation
|
|
|
|
func (e ErrorResponse) Error() string {
|
|
parts := make([]string, 0, 3)
|
|
|
|
if e.msg != "" {
|
|
parts = append(parts, e.msg)
|
|
} else if e.status != 0 {
|
|
parts = append(parts, fmt.Sprintf("status = %d", e.status))
|
|
}
|
|
if e.err != nil {
|
|
parts = append(parts, e.err.Error())
|
|
}
|
|
|
|
if len(parts) == 0 {
|
|
return "status = 500"
|
|
}
|
|
|
|
return strings.Join(parts, ": ")
|
|
}
|
|
|
|
func (e ErrorResponse) Unwrap() error {
|
|
return e.err
|
|
}
|
|
|
|
// nested response value resolution
|
|
|
|
func (e ErrorResponse) GetStatus() (int, bool) {
|
|
if e.status != 0 {
|
|
return e.status, true
|
|
}
|
|
|
|
ce, ok := GetError(e.err)
|
|
if ok {
|
|
return ce.GetStatus()
|
|
}
|
|
|
|
return 0, false
|
|
}
|
|
|
|
func (e ErrorResponse) GetMsg() (string, bool) {
|
|
if e.msg != "" {
|
|
return e.msg, true
|
|
}
|
|
|
|
ce, ok := GetError(e.err)
|
|
if ok {
|
|
return ce.GetMsg()
|
|
}
|
|
|
|
return "", false
|
|
}
|
|
|
|
func (e ErrorResponse) GetHTML() ([]byte, bool) {
|
|
if len(e.html) != 0 {
|
|
return e.html, true
|
|
}
|
|
|
|
ce, ok := GetError(e.err)
|
|
if ok {
|
|
return ce.GetHTML()
|
|
}
|
|
|
|
return nil, false
|
|
}
|
|
|
|
func GetError(err error) (e ErrorResponse, ok bool) {
|
|
ok = errors.As(err, &e)
|
|
return e, ok
|
|
}
|
|
|
|
// error wrapping utilities
|
|
|
|
func ErrorFromConstant(err error) error {
|
|
cerr := err
|
|
for cerr != nil {
|
|
switch cerr {
|
|
case consts.ErrNotFound:
|
|
return NotFound()
|
|
case consts.ErrConflict:
|
|
return Conflict()
|
|
}
|
|
|
|
uerr, ok := cerr.(interface {
|
|
Unwrap() error
|
|
})
|
|
if !ok {
|
|
return err
|
|
}
|
|
|
|
cerr = uerr.Unwrap()
|
|
}
|
|
return err
|
|
}
|