diff --git a/binding/binding_nomsgpack.go b/binding/binding_nomsgpack.go index 7f6a904a..2e868c4e 100644 --- a/binding/binding_nomsgpack.go +++ b/binding/binding_nomsgpack.go @@ -86,7 +86,7 @@ var ( // Default returns the appropriate Binding instance based on the HTTP method // and the content type. func Default(method, contentType string) Binding { - if method == "GET" { + if method == http.MethodGet { return Form } diff --git a/binding/form_mapping.go b/binding/form_mapping.go index 540bbbb8..282fb448 100644 --- a/binding/form_mapping.go +++ b/binding/form_mapping.go @@ -17,7 +17,8 @@ import ( ) var ( - errUnknownType = errors.New("unknown type") + // ErrUnknownType unknown request type + ErrUnknownType = errors.New("unknown type") // ErrConvertMapStringSlice can not convert to map[string][]string ErrConvertMapStringSlice = errors.New("can not convert to map slices of strings") @@ -240,7 +241,7 @@ func setWithProperType(val string, value reflect.Value, field reflect.StructFiel case reflect.Map: return json.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface()) default: - return errUnknownType + return ErrUnknownType } return nil } diff --git a/binding/form_mapping_test.go b/binding/form_mapping_test.go index 93d6a92f..4fecd089 100644 --- a/binding/form_mapping_test.go +++ b/binding/form_mapping_test.go @@ -124,7 +124,7 @@ func TestMappingUnknownFieldType(t *testing.T) { err := mappingByPtr(&s, formSource{"U": {"unknown"}}, "form") assert.Error(t, err) - assert.Equal(t, errUnknownType, err) + assert.Equal(t, ErrUnknownType, err) } func TestMappingURI(t *testing.T) { diff --git a/binding/json.go b/binding/json.go index 36eb27a3..5fa7ed71 100644 --- a/binding/json.go +++ b/binding/json.go @@ -13,16 +13,21 @@ import ( "github.com/gin-gonic/gin/internal/json" ) -// EnableDecoderUseNumber is used to call the UseNumber method on the JSON -// Decoder instance. UseNumber causes the Decoder to unmarshal a number into an -// interface{} as a Number instead of as a float64. -var EnableDecoderUseNumber = false +var ( + // EnableDecoderUseNumber is used to call the UseNumber method on the JSON + // Decoder instance. UseNumber causes the Decoder to unmarshal a number into an + // interface{} as a Number instead of as a float64. + EnableDecoderUseNumber = false -// EnableDecoderDisallowUnknownFields is used to call the DisallowUnknownFields method -// on the JSON Decoder instance. DisallowUnknownFields causes the Decoder to -// return an error when the destination is a struct and the input contains object -// keys which do not match any non-ignored, exported fields in the destination. -var EnableDecoderDisallowUnknownFields = false + // EnableDecoderDisallowUnknownFields is used to call the DisallowUnknownFields method + // on the JSON Decoder instance. DisallowUnknownFields causes the Decoder to + // return an error when the destination is a struct and the input contains object + // keys which do not match any non-ignored, exported fields in the destination. + EnableDecoderDisallowUnknownFields = false + + // ErrInvalidRequest request is nil or request body is nil. + ErrInvalidRequest = errors.New("invalid request") +) type jsonBinding struct{} @@ -32,8 +37,9 @@ func (jsonBinding) Name() string { func (jsonBinding) Bind(req *http.Request, obj any) error { if req == nil || req.Body == nil { - return errors.New("invalid request") + return ErrInvalidRequest } + return decodeJSON(req.Body, obj) } diff --git a/context.go b/context.go index 737e4d7a..15173b5d 100644 --- a/context.go +++ b/context.go @@ -822,11 +822,8 @@ func (c *Context) ContentType() string { // IsWebsocket returns true if the request headers indicate that a websocket // handshake is being initiated by the client. func (c *Context) IsWebsocket() bool { - if strings.Contains(strings.ToLower(c.requestHeader("Connection")), "upgrade") && - strings.EqualFold(c.requestHeader("Upgrade"), "websocket") { - return true - } - return false + return strings.Contains(strings.ToLower(c.requestHeader("Connection")), "upgrade") && + strings.EqualFold(c.requestHeader("Upgrade"), "websocket") } func (c *Context) requestHeader(key string) string { diff --git a/recovery.go b/recovery.go index 3a90f250..8908b08f 100644 --- a/recovery.go +++ b/recovery.go @@ -6,7 +6,6 @@ package gin import ( "bytes" - "errors" "fmt" "io" "log" @@ -47,6 +46,20 @@ func RecoveryWithWriter(out io.Writer, recovery ...RecoveryFunc) HandlerFunc { return CustomRecoveryWithWriter(out, defaultHandleRecovery) } +// IsBroken Check error for a broken connection +func IsBroken(err interface{}) bool { + if ne, ok := err.(*net.OpError); ok { + if se, ok := ne.Err.(*os.SyscallError); ok { + if errMsg := strings.ToLower(se.Error()); strings.Contains(errMsg, "broken pipe") || + strings.Contains(errMsg, "connection reset by peer") { + return true + } + } + } + + return false +} + // CustomRecoveryWithWriter returns a middleware for a given writer that recovers from any panics and calls the provided handle func to handle it. func CustomRecoveryWithWriter(out io.Writer, handle RecoveryFunc) HandlerFunc { var logger *log.Logger @@ -58,15 +71,7 @@ func CustomRecoveryWithWriter(out io.Writer, handle RecoveryFunc) HandlerFunc { if err := recover(); err != nil { // Check for a broken connection, as it is not really a // condition that warrants a panic stack trace. - var brokenPipe bool - if ne, ok := err.(*net.OpError); ok { - var se *os.SyscallError - if errors.As(ne, &se) { - if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") { - brokenPipe = true - } - } - } + var brokenPipe = IsBroken(err) if logger != nil { stack := stack(3) httpRequest, _ := httputil.DumpRequest(c.Request, false)