123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- package rest
- import (
- "net/http"
- )
- // REST API error.
- var (
- Err = Error{}
- ErrMovedPermanently = NewError(http.StatusMovedPermanently, "") // 301
- ErrFound = NewError(http.StatusFound, "") // 302
- ErrTemporaryRedirect = NewError(http.StatusTemporaryRedirect, "") // 307
- ErrPermanentRedirect = NewError(http.StatusPermanentRedirect, "") // 308
- ErrBadRequest = NewError(http.StatusBadRequest, "") // 400
- ErrUnauthorized = NewError(http.StatusUnauthorized, "") // 401
- ErrPaymentRequired = NewError(http.StatusPaymentRequired, "") // 402
- ErrForbidden = NewError(http.StatusForbidden, "") // 403
- ErrNotFound = NewError(http.StatusNotFound, "") // 404
- ErrMethodNotAllowed = NewError(http.StatusMethodNotAllowed, "") // 405
- ErrNotAcceptable = NewError(http.StatusNotAcceptable, "") // 406
- ErrInternalServerError = NewError(http.StatusInternalServerError, "") // 500
- ErrNotImplemented = NewError(http.StatusNotImplemented, "") // 501
- ErrBadGateway = NewError(http.StatusBadGateway, "") // 502
- ErrServiceUnavailable = NewError(http.StatusServiceUnavailable, "") // 503
- ErrGatewayTimeout = NewError(http.StatusGatewayTimeout, "") // 504
- )
- // Error represents a REST API error.
- // It can be marshaled to JSON with ease and provides a standard format for printing errors and additional data.
- type Error struct {
- StatusCode int `json:"-"` // HTTP status code (200, 404, 500 etc.)
- Message string `json:"message"` // Status message ("OK", "Not found", "Internal server error" etc.)
- Data map[string]interface{} `json:"data,omitempty"` // Optional additional data.
- }
- // Error retrieves the message of a REST API error.
- func (e Error) Error() string {
- return e.Message
- }
- // Is determines whether the Error is an instance of the target.
- // https://pkg.go.dev/errors#Is
- //
- // If the target is a REST API error and specifies a status code, this function returns true if the status codes match.
- // If the target is an empty REST API error, this function always returns true.
- func (e Error) Is(target error) bool {
- if t, ok := target.(Error); ok {
- return t.StatusCode == e.StatusCode || t.StatusCode == 0
- }
- return false
- }
- // WithData returns a copy of the HTTP error with the given data merged in.
- func (e Error) WithData(data map[string]interface{}) Error {
- if e.Data == nil {
- e.Data = map[string]any{}
- }
- if data != nil {
- for key, value := range data {
- e.Data[key] = value
- }
- }
- return e
- }
- // WithError returns a copy of the HTTP error with the given error added either as the Message, if it empty, or as additional data.
- func (e Error) WithError(err error) Error {
- if e.Message == "" {
- return e.WithMessage(err.Error())
- }
- return e.WithData(map[string]interface{}{
- "error": err.Error(),
- })
- }
- // WithMessage returns a copy of the HTTP error with the given message.
- func (e Error) WithMessage(message string) Error {
- e.Message = message
- return e
- }
- // WithValue returns a copy of the HTTP error with a single data value added.
- func (e Error) WithValue(name string, value any) Error {
- return e.WithData(map[string]any{
- name: value,
- })
- }
- // Write writes the HTTP error to an HTTP response as plain text.
- // Additional data is omitted.
- func (e Error) Write(w http.ResponseWriter) (int, error) {
- if e.StatusCode == 0 {
- e.StatusCode = 200
- }
- w.WriteHeader(e.StatusCode)
- return w.Write([]byte(e.Message))
- }
- // WriteJSON writes the HTTP error to an HTTP response as JSON.
- func (e Error) WriteJSON(w http.ResponseWriter) error {
- if e.StatusCode == 0 {
- e.StatusCode = 200
- }
- return WriteResponseJSON(w, e.StatusCode, e)
- }
- // NewError creates a new REST API error.
- // If the message is empty, the standard text provided by http.StatusText is substituted.
- func NewError(statusCode int, message string) Error {
- if len(message) == 0 {
- message = http.StatusText(statusCode)
- }
- return Error{
- StatusCode: statusCode,
- Message: message,
- }
- }
|