mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-16 13:22:09 +08:00
This allows the GoDoc to take advantage of new markup syntax introduced in Go 1.19. This does not require that our minimum supported version be bumped to Go 1.19 since the pkgsite renders our godoc regardless of supported Go version.
176 lines
3.9 KiB
Go
176 lines
3.9 KiB
Go
// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
|
|
// Use of this source code is governed by a MIT style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package gin
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin/internal/json"
|
|
)
|
|
|
|
// ErrorType is an unsigned 64-bit error code as defined in the gin spec.
|
|
type ErrorType uint64
|
|
|
|
const (
|
|
// ErrorTypeBind is used when Context.Bind() fails.
|
|
ErrorTypeBind ErrorType = 1 << 63
|
|
// ErrorTypeRender is used when Context.Render() fails.
|
|
ErrorTypeRender ErrorType = 1 << 62
|
|
// ErrorTypePrivate indicates a private error.
|
|
ErrorTypePrivate ErrorType = 1 << 0
|
|
// ErrorTypePublic indicates a public error.
|
|
ErrorTypePublic ErrorType = 1 << 1
|
|
// ErrorTypeAny indicates any other error.
|
|
ErrorTypeAny ErrorType = 1<<64 - 1
|
|
// ErrorTypeNu indicates any other error.
|
|
ErrorTypeNu = 2
|
|
)
|
|
|
|
// Error represents a error's specification.
|
|
type Error struct {
|
|
Err error
|
|
Type ErrorType
|
|
Meta any
|
|
}
|
|
|
|
type errorMsgs []*Error
|
|
|
|
var _ error = &Error{}
|
|
|
|
// SetType sets the error's type.
|
|
func (msg *Error) SetType(flags ErrorType) *Error {
|
|
msg.Type = flags
|
|
return msg
|
|
}
|
|
|
|
// SetMeta sets the error's meta data.
|
|
func (msg *Error) SetMeta(data any) *Error {
|
|
msg.Meta = data
|
|
return msg
|
|
}
|
|
|
|
// JSON creates a properly formatted JSON
|
|
func (msg *Error) JSON() any {
|
|
jsonData := H{}
|
|
if msg.Meta != nil {
|
|
value := reflect.ValueOf(msg.Meta)
|
|
switch value.Kind() {
|
|
case reflect.Struct:
|
|
return msg.Meta
|
|
case reflect.Map:
|
|
for _, key := range value.MapKeys() {
|
|
jsonData[key.String()] = value.MapIndex(key).Interface()
|
|
}
|
|
default:
|
|
jsonData["meta"] = msg.Meta
|
|
}
|
|
}
|
|
if _, ok := jsonData["error"]; !ok {
|
|
jsonData["error"] = msg.Error()
|
|
}
|
|
return jsonData
|
|
}
|
|
|
|
// MarshalJSON implements the json.Marshaller interface.
|
|
func (msg *Error) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(msg.JSON())
|
|
}
|
|
|
|
// Error implements the error interface.
|
|
func (msg Error) Error() string {
|
|
return msg.Err.Error()
|
|
}
|
|
|
|
// IsType judges one error.
|
|
func (msg *Error) IsType(flags ErrorType) bool {
|
|
return (msg.Type & flags) > 0
|
|
}
|
|
|
|
// Unwrap returns the wrapped error, to allow interoperability with errors.Is(), errors.As() and errors.Unwrap()
|
|
func (msg *Error) Unwrap() error {
|
|
return msg.Err
|
|
}
|
|
|
|
// ByType returns a readonly copy filtered the byte.
|
|
// ie ByType(gin.ErrorTypePublic) returns a slice of errors with type=ErrorTypePublic.
|
|
func (a errorMsgs) ByType(typ ErrorType) errorMsgs {
|
|
if len(a) == 0 {
|
|
return nil
|
|
}
|
|
if typ == ErrorTypeAny {
|
|
return a
|
|
}
|
|
var result errorMsgs
|
|
for _, msg := range a {
|
|
if msg.IsType(typ) {
|
|
result = append(result, msg)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// Last returns the last error in the slice. It returns nil if the array is empty.
|
|
// Shortcut for errors[len(errors)-1].
|
|
func (a errorMsgs) Last() *Error {
|
|
if length := len(a); length > 0 {
|
|
return a[length-1]
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Errors returns an array with all the error messages.
|
|
// Example:
|
|
//
|
|
// c.Error(errors.New("first"))
|
|
// c.Error(errors.New("second"))
|
|
// c.Error(errors.New("third"))
|
|
// c.Errors.Errors() // == []string{"first", "second", "third"}
|
|
func (a errorMsgs) Errors() []string {
|
|
if len(a) == 0 {
|
|
return nil
|
|
}
|
|
errorStrings := make([]string, len(a))
|
|
for i, err := range a {
|
|
errorStrings[i] = err.Error()
|
|
}
|
|
return errorStrings
|
|
}
|
|
|
|
func (a errorMsgs) JSON() any {
|
|
switch length := len(a); length {
|
|
case 0:
|
|
return nil
|
|
case 1:
|
|
return a.Last().JSON()
|
|
default:
|
|
jsonData := make([]any, length)
|
|
for i, err := range a {
|
|
jsonData[i] = err.JSON()
|
|
}
|
|
return jsonData
|
|
}
|
|
}
|
|
|
|
// MarshalJSON implements the json.Marshaller interface.
|
|
func (a errorMsgs) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(a.JSON())
|
|
}
|
|
|
|
func (a errorMsgs) String() string {
|
|
if len(a) == 0 {
|
|
return ""
|
|
}
|
|
var buffer strings.Builder
|
|
for i, msg := range a {
|
|
fmt.Fprintf(&buffer, "Error #%02d: %s\n", i+1, msg.Err)
|
|
if msg.Meta != nil {
|
|
fmt.Fprintf(&buffer, " Meta: %v\n", msg.Meta)
|
|
}
|
|
}
|
|
return buffer.String()
|
|
}
|