Merge remote-tracking branch 'upstream/master'

This commit is contained in:
thinkerou 2021-11-25 09:38:13 +08:00
commit 9a9eb9536f
8 changed files with 54 additions and 22 deletions

View File

@ -21,7 +21,7 @@ jobs:
- name: Setup golangci-lint - name: Setup golangci-lint
uses: golangci/golangci-lint-action@v2 uses: golangci/golangci-lint-action@v2
with: with:
version: v1.42.1 version: v1.43.0
args: --verbose args: --verbose
test: test:
needs: lint needs: lint

View File

@ -1,5 +1,35 @@
# Gin ChangeLog # Gin ChangeLog
## Gin v1.7.7
### BUGFIXES
* Fixed X-Forwarded-For unsafe handling of CVE-2020-28483 [#2844](https://github.com/gin-gonic/gin/pull/2844), closed issue [#2862](https://github.com/gin-gonic/gin/issues/2862).
* Tree: updated the code logic for `latestNode` [#2897](https://github.com/gin-gonic/gin/pull/2897), closed issue [#2894](https://github.com/gin-gonic/gin/issues/2894) [#2878](https://github.com/gin-gonic/gin/issues/2878).
* Tree: fixed the misplacement of adding slashes [#2847](https://github.com/gin-gonic/gin/pull/2847), closed issue [#2843](https://github.com/gin-gonic/gin/issues/2843).
* Tree: fixed tsr with mixed static and wildcard paths [#2924](https://github.com/gin-gonic/gin/pull/2924), closed issue [#2918](https://github.com/gin-gonic/gin/issues/2918).
### ENHANCEMENTS
* TrustedProxies: make it backward-compatible [#2887](https://github.com/gin-gonic/gin/pull/2887), closed issue [#2819](https://github.com/gin-gonic/gin/issues/2819).
* TrustedPlatform: provide custom options for another CDN services [#2906](https://github.com/gin-gonic/gin/pull/2906).
### DOCS
* NoMethod: added usage annotation ([#2832](https://github.com/gin-gonic/gin/pull/2832#issuecomment-929954463)).
## Gin v1.7.6
### BUGFIXES
* bump new release to fix v1.7.5 release error by using v1.7.4 codes.
## Gin v1.7.4
### BUGFIXES
* bump new release to fix checksum mismatch
## Gin v1.7.3 ## Gin v1.7.3
### BUGFIXES ### BUGFIXES

View File

@ -18,10 +18,10 @@ type defaultValidator struct {
validate *validator.Validate validate *validator.Validate
} }
type sliceValidateError []error type SliceValidationError []error
// Error concatenates all error elements in sliceValidateError into a single string separated by \n. // Error concatenates all error elements in SliceValidationError into a single string separated by \n.
func (err sliceValidateError) Error() string { func (err SliceValidationError) Error() string {
n := len(err) n := len(err)
switch n { switch n {
case 0: case 0:
@ -59,7 +59,7 @@ func (v *defaultValidator) ValidateStruct(obj interface{}) error {
return v.validateStruct(obj) return v.validateStruct(obj)
case reflect.Slice, reflect.Array: case reflect.Slice, reflect.Array:
count := value.Len() count := value.Len()
validateRet := make(sliceValidateError, 0) validateRet := make(SliceValidationError, 0)
for i := 0; i < count; i++ { for i := 0; i < count; i++ {
if err := v.ValidateStruct(value.Index(i).Interface()); err != nil { if err := v.ValidateStruct(value.Index(i).Interface()); err != nil {
validateRet = append(validateRet, err) validateRet = append(validateRet, err)

View File

@ -6,10 +6,10 @@ import (
"testing" "testing"
) )
func BenchmarkSliceValidateError(b *testing.B) { func BenchmarkSliceValidationError(b *testing.B) {
const size int = 100 const size int = 100
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
e := make(sliceValidateError, size) e := make(SliceValidationError, size)
for j := 0; j < size; j++ { for j := 0; j < size; j++ {
e[j] = errors.New(strconv.Itoa(j)) e[j] = errors.New(strconv.Itoa(j))
} }

View File

@ -9,24 +9,24 @@ import (
"testing" "testing"
) )
func TestSliceValidateError(t *testing.T) { func TestSliceValidationError(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
err sliceValidateError err SliceValidationError
want string want string
}{ }{
{"has nil elements", sliceValidateError{errors.New("test error"), nil}, "[0]: test error"}, {"has nil elements", SliceValidationError{errors.New("test error"), nil}, "[0]: test error"},
{"has zero elements", sliceValidateError{}, ""}, {"has zero elements", SliceValidationError{}, ""},
{"has one element", sliceValidateError{errors.New("test one error")}, "[0]: test one error"}, {"has one element", SliceValidationError{errors.New("test one error")}, "[0]: test one error"},
{"has two elements", {"has two elements",
sliceValidateError{ SliceValidationError{
errors.New("first error"), errors.New("first error"),
errors.New("second error"), errors.New("second error"),
}, },
"[0]: first error\n[1]: second error", "[0]: first error\n[1]: second error",
}, },
{"has many elements", {"has many elements",
sliceValidateError{ SliceValidationError{
errors.New("first error"), errors.New("first error"),
errors.New("second error"), errors.New("second error"),
nil, nil,
@ -40,7 +40,7 @@ func TestSliceValidateError(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
if got := tt.err.Error(); got != tt.want { if got := tt.err.Error(); got != tt.want {
t.Errorf("sliceValidateError.Error() = %v, want %v", got, tt.want) t.Errorf("SliceValidationError.Error() = %v, want %v", got, tt.want)
} }
}) })
} }

View File

@ -252,7 +252,7 @@ func (c *Context) Set(key string, value interface{}) {
} }
// Get returns the value for the given key, ie: (value, true). // Get returns the value for the given key, ie: (value, true).
// If the value does not exists it returns (nil, false) // If the value does not exist it returns (nil, false)
func (c *Context) Get(key string) (value interface{}, exists bool) { func (c *Context) Get(key string) (value interface{}, exists bool) {
c.mu.RLock() c.mu.RLock()
value, exists = c.Keys[key] value, exists = c.Keys[key]
@ -602,7 +602,7 @@ func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst string) error
} }
// Bind checks the Content-Type to select a binding engine automatically, // Bind checks the Content-Type to select a binding engine automatically,
// Depending the "Content-Type" header different bindings are used: // Depending on the "Content-Type" header different bindings are used:
// "application/json" --> JSON binding // "application/json" --> JSON binding
// "application/xml" --> XML binding // "application/xml" --> XML binding
// otherwise --> returns an error. // otherwise --> returns an error.
@ -661,7 +661,7 @@ func (c *Context) MustBindWith(obj interface{}, b binding.Binding) error {
} }
// ShouldBind checks the Content-Type to select a binding engine automatically, // ShouldBind checks the Content-Type to select a binding engine automatically,
// Depending the "Content-Type" header different bindings are used: // Depending on the "Content-Type" header different bindings are used:
// "application/json" --> JSON binding // "application/json" --> JSON binding
// "application/xml" --> XML binding // "application/xml" --> XML binding
// otherwise --> returns an error // otherwise --> returns an error
@ -863,7 +863,7 @@ func (c *Context) Status(code int) {
c.Writer.WriteHeader(code) c.Writer.WriteHeader(code)
} }
// Header is a intelligent shortcut for c.Writer.Header().Set(key, value). // Header is an intelligent shortcut for c.Writer.Header().Set(key, value).
// It writes a header in the response. // It writes a header in the response.
// If value == "", this method removes the header `c.Writer.Header().Del(key)` // If value == "", this method removes the header `c.Writer.Header().Del(key)`
func (c *Context) Header(key, value string) { func (c *Context) Header(key, value string) {
@ -946,7 +946,7 @@ func (c *Context) HTML(code int, name string, obj interface{}) {
// IndentedJSON serializes the given struct as pretty JSON (indented + endlines) into the response body. // IndentedJSON serializes the given struct as pretty JSON (indented + endlines) into the response body.
// It also sets the Content-Type as "application/json". // It also sets the Content-Type as "application/json".
// WARNING: we recommend to use this only for development purposes since printing pretty JSON is // WARNING: we recommend using this only for development purposes since printing pretty JSON is
// more CPU and bandwidth consuming. Use Context.JSON() instead. // more CPU and bandwidth consuming. Use Context.JSON() instead.
func (c *Context) IndentedJSON(code int, obj interface{}) { func (c *Context) IndentedJSON(code int, obj interface{}) {
c.Render(code, render.IndentedJSON{Data: obj}) c.Render(code, render.IndentedJSON{Data: obj})
@ -1010,7 +1010,7 @@ func (c *Context) String(code int, format string, values ...interface{}) {
c.Render(code, render.String{Format: format, Data: values}) c.Render(code, render.String{Format: format, Data: values})
} }
// Redirect returns a HTTP redirect to the specific location. // Redirect returns an HTTP redirect to the specific location.
func (c *Context) Redirect(code int, location string) { func (c *Context) Redirect(code int, location string) {
c.Render(-1, render.Redirect{ c.Render(-1, render.Redirect{
Code: code, Code: code,

2
go.mod
View File

@ -13,3 +13,5 @@ require (
google.golang.org/protobuf v1.27.1 google.golang.org/protobuf v1.27.1
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
) )
retract v1.7.5

View File

@ -5,4 +5,4 @@
package gin package gin
// Version is the current gin framework's version. // Version is the current gin framework's version.
const Version = "v1.7.4" const Version = "v1.7.7"