mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-16 21:32:11 +08:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
9a9eb9536f
2
.github/workflows/gin.yml
vendored
2
.github/workflows/gin.yml
vendored
@ -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
|
||||||
|
30
CHANGELOG.md
30
CHANGELOG.md
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
12
context.go
12
context.go
@ -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
2
go.mod
@ -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
|
||||||
|
@ -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"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user