Merge 21fe9c2f2b635ec56da72746395b38e68caaa07f into 2285aa5430fb5e68bb55a89009fc4f5dd261b466

This commit is contained in:
heige 2022-12-22 08:02:05 +09:00 committed by GitHub
commit 734c73f388
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 38 additions and 29 deletions

View File

@ -86,7 +86,7 @@ var (
// Default returns the appropriate Binding instance based on the HTTP method // Default returns the appropriate Binding instance based on the HTTP method
// and the content type. // and the content type.
func Default(method, contentType string) Binding { func Default(method, contentType string) Binding {
if method == "GET" { if method == http.MethodGet {
return Form return Form
} }

View File

@ -17,7 +17,8 @@ import (
) )
var ( var (
errUnknownType = errors.New("unknown type") // ErrUnknownType unknown request type
ErrUnknownType = errors.New("unknown type")
// ErrConvertMapStringSlice can not convert to map[string][]string // ErrConvertMapStringSlice can not convert to map[string][]string
ErrConvertMapStringSlice = errors.New("can not convert to map slices of strings") 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: case reflect.Map:
return json.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface()) return json.Unmarshal(bytesconv.StringToBytes(val), value.Addr().Interface())
default: default:
return errUnknownType return ErrUnknownType
} }
return nil return nil
} }

View File

@ -124,7 +124,7 @@ func TestMappingUnknownFieldType(t *testing.T) {
err := mappingByPtr(&s, formSource{"U": {"unknown"}}, "form") err := mappingByPtr(&s, formSource{"U": {"unknown"}}, "form")
assert.Error(t, err) assert.Error(t, err)
assert.Equal(t, errUnknownType, err) assert.Equal(t, ErrUnknownType, err)
} }
func TestMappingURI(t *testing.T) { func TestMappingURI(t *testing.T) {

View File

@ -13,16 +13,21 @@ import (
"github.com/gin-gonic/gin/internal/json" "github.com/gin-gonic/gin/internal/json"
) )
var (
// EnableDecoderUseNumber is used to call the UseNumber method on the JSON // EnableDecoderUseNumber is used to call the UseNumber method on the JSON
// Decoder instance. UseNumber causes the Decoder to unmarshal a number into an // Decoder instance. UseNumber causes the Decoder to unmarshal a number into an
// interface{} as a Number instead of as a float64. // interface{} as a Number instead of as a float64.
var EnableDecoderUseNumber = false EnableDecoderUseNumber = false
// EnableDecoderDisallowUnknownFields is used to call the DisallowUnknownFields method // EnableDecoderDisallowUnknownFields is used to call the DisallowUnknownFields method
// on the JSON Decoder instance. DisallowUnknownFields causes the Decoder to // on the JSON Decoder instance. DisallowUnknownFields causes the Decoder to
// return an error when the destination is a struct and the input contains object // 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. // keys which do not match any non-ignored, exported fields in the destination.
var EnableDecoderDisallowUnknownFields = false EnableDecoderDisallowUnknownFields = false
// ErrInvalidRequest request is nil or request body is nil.
ErrInvalidRequest = errors.New("invalid request")
)
type jsonBinding struct{} type jsonBinding struct{}
@ -32,8 +37,9 @@ func (jsonBinding) Name() string {
func (jsonBinding) Bind(req *http.Request, obj any) error { func (jsonBinding) Bind(req *http.Request, obj any) error {
if req == nil || req.Body == nil { if req == nil || req.Body == nil {
return errors.New("invalid request") return ErrInvalidRequest
} }
return decodeJSON(req.Body, obj) return decodeJSON(req.Body, obj)
} }

View File

@ -822,11 +822,8 @@ func (c *Context) ContentType() string {
// IsWebsocket returns true if the request headers indicate that a websocket // IsWebsocket returns true if the request headers indicate that a websocket
// handshake is being initiated by the client. // handshake is being initiated by the client.
func (c *Context) IsWebsocket() bool { func (c *Context) IsWebsocket() bool {
if strings.Contains(strings.ToLower(c.requestHeader("Connection")), "upgrade") && return strings.Contains(strings.ToLower(c.requestHeader("Connection")), "upgrade") &&
strings.EqualFold(c.requestHeader("Upgrade"), "websocket") { strings.EqualFold(c.requestHeader("Upgrade"), "websocket")
return true
}
return false
} }
func (c *Context) requestHeader(key string) string { func (c *Context) requestHeader(key string) string {

View File

@ -6,7 +6,6 @@ package gin
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"io" "io"
"log" "log"
@ -47,6 +46,20 @@ func RecoveryWithWriter(out io.Writer, recovery ...RecoveryFunc) HandlerFunc {
return CustomRecoveryWithWriter(out, defaultHandleRecovery) 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. // 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 { func CustomRecoveryWithWriter(out io.Writer, handle RecoveryFunc) HandlerFunc {
var logger *log.Logger var logger *log.Logger
@ -58,15 +71,7 @@ func CustomRecoveryWithWriter(out io.Writer, handle RecoveryFunc) HandlerFunc {
if err := recover(); err != nil { if err := recover(); err != nil {
// Check for a broken connection, as it is not really a // Check for a broken connection, as it is not really a
// condition that warrants a panic stack trace. // condition that warrants a panic stack trace.
var brokenPipe bool var brokenPipe = IsBroken(err)
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
}
}
}
if logger != nil { if logger != nil {
stack := stack(3) stack := stack(3)
httpRequest, _ := httputil.DumpRequest(c.Request, false) httpRequest, _ := httputil.DumpRequest(c.Request, false)