chore: support min go version 1.18 (#3511)
* chore: min go version 1.18
* fix build tag error
* remove build tag
* fix word
* remove any.go
* replace interface{} instead of any
			
			
This commit is contained in:
		
							
								
								
									
										6
									
								
								.github/workflows/gin.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/gin.yml
									
									
									
									
										vendored
									
									
								
							@ -18,7 +18,7 @@ jobs:
 | 
				
			|||||||
      - name: Setup go
 | 
					      - name: Setup go
 | 
				
			||||||
        uses: actions/setup-go@v3
 | 
					        uses: actions/setup-go@v3
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          go-version: '^1.16'
 | 
					          go-version: '^1.18'
 | 
				
			||||||
      - name: Checkout repository
 | 
					      - name: Checkout repository
 | 
				
			||||||
        uses: actions/checkout@v3
 | 
					        uses: actions/checkout@v3
 | 
				
			||||||
      - name: Setup golangci-lint
 | 
					      - name: Setup golangci-lint
 | 
				
			||||||
@ -31,7 +31,7 @@ jobs:
 | 
				
			|||||||
    strategy:
 | 
					    strategy:
 | 
				
			||||||
      matrix:
 | 
					      matrix:
 | 
				
			||||||
        os: [ubuntu-latest, macos-latest]
 | 
					        os: [ubuntu-latest, macos-latest]
 | 
				
			||||||
        go: ['1.16', '1.17', '1.18', '1.19', '1.20']
 | 
					        go: ['1.18', '1.19', '1.20']
 | 
				
			||||||
        test-tags: ['', '-tags nomsgpack', '-tags "sonic avx"', '-tags go_json']
 | 
					        test-tags: ['', '-tags nomsgpack', '-tags "sonic avx"', '-tags go_json']
 | 
				
			||||||
        include:
 | 
					        include:
 | 
				
			||||||
          - os: ubuntu-latest
 | 
					          - os: ubuntu-latest
 | 
				
			||||||
@ -73,7 +73,7 @@ jobs:
 | 
				
			|||||||
          flags: ${{ matrix.os }},go-${{ matrix.go }},${{ matrix.test-tags }}
 | 
					          flags: ${{ matrix.os }},go-${{ matrix.go }},${{ matrix.test-tags }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Format
 | 
					      - name: Format
 | 
				
			||||||
        if: matrix.go-version == '1.19.x'
 | 
					        if: matrix.go-version == '1.20.x'
 | 
				
			||||||
        run: diff -u <(echo -n) <(gofmt -d .)
 | 
					        run: diff -u <(echo -n) <(gofmt -d .)
 | 
				
			||||||
  notification-gitter:
 | 
					  notification-gitter:
 | 
				
			||||||
    needs: test
 | 
					    needs: test
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								.github/workflows/goreleaser.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/goreleaser.yml
									
									
									
									
										vendored
									
									
								
							@ -21,7 +21,7 @@ jobs:
 | 
				
			|||||||
        name: Set up Go
 | 
					        name: Set up Go
 | 
				
			||||||
        uses: actions/setup-go@v3
 | 
					        uses: actions/setup-go@v3
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          go-version: 1.17
 | 
					          go-version: 1.20
 | 
				
			||||||
      -
 | 
					      -
 | 
				
			||||||
        name: Run GoReleaser
 | 
					        name: Run GoReleaser
 | 
				
			||||||
        uses: goreleaser/goreleaser-action@v4
 | 
					        uses: goreleaser/goreleaser-action@v4
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@ Gin is a web framework written in [Go](https://go.dev/). It features a martini-l
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### Prerequisites
 | 
					### Prerequisites
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- **[Go](https://go.dev/)**: ~~any one of the **three latest major** [releases](https://go.dev/doc/devel/release)~~ (now version **1.16+** is required).
 | 
					- **[Go](https://go.dev/)**: any one of the **three latest major** [releases](https://go.dev/doc/devel/release) (we test it with these).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Getting Gin
 | 
					### Getting Gin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								any.go
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								any.go
									
									
									
									
									
								
							@ -1,10 +0,0 @@
 | 
				
			|||||||
// Copyright 2022 Gin Core Team. All rights reserved.
 | 
					 | 
				
			||||||
// Use of this source code is governed by a MIT style
 | 
					 | 
				
			||||||
// license that can be found in the LICENSE file.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//go:build !go1.18
 | 
					 | 
				
			||||||
// +build !go1.18
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package gin
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type any = interface{}
 | 
					 | 
				
			||||||
@ -1,10 +0,0 @@
 | 
				
			|||||||
// Copyright 2022 Gin Core Team. All rights reserved.
 | 
					 | 
				
			||||||
// Use of this source code is governed by a MIT style
 | 
					 | 
				
			||||||
// license that can be found in the LICENSE file.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//go:build !go1.18
 | 
					 | 
				
			||||||
// +build !go1.18
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package binding
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type any = interface{}
 | 
					 | 
				
			||||||
@ -3,7 +3,6 @@
 | 
				
			|||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:build !nomsgpack
 | 
					//go:build !nomsgpack
 | 
				
			||||||
// +build !nomsgpack
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package binding
 | 
					package binding
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,6 @@
 | 
				
			|||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:build !nomsgpack
 | 
					//go:build !nomsgpack
 | 
				
			||||||
// +build !nomsgpack
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package binding
 | 
					package binding
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,6 @@
 | 
				
			|||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:build nomsgpack
 | 
					//go:build nomsgpack
 | 
				
			||||||
// +build nomsgpack
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package binding
 | 
					package binding
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// 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.
 | 
					// any as a Number instead of as a float64.
 | 
				
			||||||
var EnableDecoderUseNumber = false
 | 
					var EnableDecoderUseNumber = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EnableDecoderDisallowUnknownFields is used to call the DisallowUnknownFields method
 | 
					// EnableDecoderDisallowUnknownFields is used to call the DisallowUnknownFields method
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,6 @@
 | 
				
			|||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:build !nomsgpack
 | 
					//go:build !nomsgpack
 | 
				
			||||||
// +build !nomsgpack
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package binding
 | 
					package binding
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,6 @@
 | 
				
			|||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:build !nomsgpack
 | 
					//go:build !nomsgpack
 | 
				
			||||||
// +build !nomsgpack
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package binding
 | 
					package binding
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -652,7 +652,7 @@ func (c *Context) BindYAML(obj any) error {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BindTOML is a shortcut for c.MustBindWith(obj, binding.TOML).
 | 
					// BindTOML is a shortcut for c.MustBindWith(obj, binding.TOML).
 | 
				
			||||||
func (c *Context) BindTOML(obj interface{}) error {
 | 
					func (c *Context) BindTOML(obj any) error {
 | 
				
			||||||
	return c.MustBindWith(obj, binding.TOML)
 | 
						return c.MustBindWith(obj, binding.TOML)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -717,7 +717,7 @@ func (c *Context) ShouldBindYAML(obj any) error {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ShouldBindTOML is a shortcut for c.ShouldBindWith(obj, binding.TOML).
 | 
					// ShouldBindTOML is a shortcut for c.ShouldBindWith(obj, binding.TOML).
 | 
				
			||||||
func (c *Context) ShouldBindTOML(obj interface{}) error {
 | 
					func (c *Context) ShouldBindTOML(obj any) error {
 | 
				
			||||||
	return c.ShouldBindWith(obj, binding.TOML)
 | 
						return c.ShouldBindWith(obj, binding.TOML)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -995,7 +995,7 @@ func (c *Context) YAML(code int, obj any) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TOML serializes the given struct as TOML into the response body.
 | 
					// TOML serializes the given struct as TOML into the response body.
 | 
				
			||||||
func (c *Context) TOML(code int, obj interface{}) {
 | 
					func (c *Context) TOML(code int, obj any) {
 | 
				
			||||||
	c.Render(code, render.TOML{Data: obj})
 | 
						c.Render(code, render.TOML{Data: obj})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,94 +0,0 @@
 | 
				
			|||||||
// Copyright 2021 Gin Core Team. All rights reserved.
 | 
					 | 
				
			||||||
// Use of this source code is governed by a MIT style
 | 
					 | 
				
			||||||
// license that can be found in the LICENSE file.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//go:build go1.17
 | 
					 | 
				
			||||||
// +build go1.17
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package gin
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"mime/multipart"
 | 
					 | 
				
			||||||
	"net/http"
 | 
					 | 
				
			||||||
	"net/http/httptest"
 | 
					 | 
				
			||||||
	"runtime"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/stretchr/testify/assert"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type interceptedWriter struct {
 | 
					 | 
				
			||||||
	ResponseWriter
 | 
					 | 
				
			||||||
	b *bytes.Buffer
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (i interceptedWriter) WriteHeader(code int) {
 | 
					 | 
				
			||||||
	i.Header().Del("X-Test")
 | 
					 | 
				
			||||||
	i.ResponseWriter.WriteHeader(code)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestContextFormFileFailed17(t *testing.T) {
 | 
					 | 
				
			||||||
	if !isGo117OrGo118() {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	buf := new(bytes.Buffer)
 | 
					 | 
				
			||||||
	mw := multipart.NewWriter(buf)
 | 
					 | 
				
			||||||
	defer func(mw *multipart.Writer) {
 | 
					 | 
				
			||||||
		err := mw.Close()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			assert.Error(t, err)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}(mw)
 | 
					 | 
				
			||||||
	c, _ := CreateTestContext(httptest.NewRecorder())
 | 
					 | 
				
			||||||
	c.Request, _ = http.NewRequest("POST", "/", nil)
 | 
					 | 
				
			||||||
	c.Request.Header.Set("Content-Type", mw.FormDataContentType())
 | 
					 | 
				
			||||||
	c.engine.MaxMultipartMemory = 8 << 20
 | 
					 | 
				
			||||||
	assert.Panics(t, func() {
 | 
					 | 
				
			||||||
		f, err := c.FormFile("file")
 | 
					 | 
				
			||||||
		assert.Error(t, err)
 | 
					 | 
				
			||||||
		assert.Nil(t, f)
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestInterceptedHeader(t *testing.T) {
 | 
					 | 
				
			||||||
	w := httptest.NewRecorder()
 | 
					 | 
				
			||||||
	c, r := CreateTestContext(w)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	r.Use(func(c *Context) {
 | 
					 | 
				
			||||||
		i := interceptedWriter{
 | 
					 | 
				
			||||||
			ResponseWriter: c.Writer,
 | 
					 | 
				
			||||||
			b:              bytes.NewBuffer(nil),
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		c.Writer = i
 | 
					 | 
				
			||||||
		c.Next()
 | 
					 | 
				
			||||||
		c.Header("X-Test", "overridden")
 | 
					 | 
				
			||||||
		c.Writer = i.ResponseWriter
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	r.GET("/", func(c *Context) {
 | 
					 | 
				
			||||||
		c.Header("X-Test", "original")
 | 
					 | 
				
			||||||
		c.Header("X-Test-2", "present")
 | 
					 | 
				
			||||||
		c.String(http.StatusOK, "hello world")
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	c.Request = httptest.NewRequest("GET", "/", nil)
 | 
					 | 
				
			||||||
	r.HandleContext(c)
 | 
					 | 
				
			||||||
	// Result() has headers frozen when WriteHeaderNow() has been called
 | 
					 | 
				
			||||||
	// Compared to this time, this is when the response headers will be flushed
 | 
					 | 
				
			||||||
	// As response is flushed on c.String, the Header cannot be set by the first
 | 
					 | 
				
			||||||
	// middleware. Assert this
 | 
					 | 
				
			||||||
	assert.Equal(t, "", w.Result().Header.Get("X-Test"))
 | 
					 | 
				
			||||||
	assert.Equal(t, "present", w.Result().Header.Get("X-Test-2"))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func isGo117OrGo118() bool {
 | 
					 | 
				
			||||||
	version := strings.Split(runtime.Version()[2:], ".")
 | 
					 | 
				
			||||||
	if len(version) >= 2 {
 | 
					 | 
				
			||||||
		x := version[0]
 | 
					 | 
				
			||||||
		y := version[1]
 | 
					 | 
				
			||||||
		if x == "1" && (y == "17" || y == "18") {
 | 
					 | 
				
			||||||
			return true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -2,8 +2,7 @@
 | 
				
			|||||||
// Use of this source code is governed by a MIT style
 | 
					// Use of this source code is governed by a MIT style
 | 
				
			||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:build !go1.17
 | 
					//go:build !go1.19
 | 
				
			||||||
// +build !go1.17
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package gin
 | 
					package gin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -17,15 +16,22 @@ import (
 | 
				
			|||||||
	"github.com/stretchr/testify/assert"
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestContextFormFileFailed16(t *testing.T) {
 | 
					func TestContextFormFileFailed18(t *testing.T) {
 | 
				
			||||||
	buf := new(bytes.Buffer)
 | 
						buf := new(bytes.Buffer)
 | 
				
			||||||
	mw := multipart.NewWriter(buf)
 | 
						mw := multipart.NewWriter(buf)
 | 
				
			||||||
	mw.Close()
 | 
						defer func(mw *multipart.Writer) {
 | 
				
			||||||
 | 
							err := mw.Close()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								assert.Error(t, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}(mw)
 | 
				
			||||||
	c, _ := CreateTestContext(httptest.NewRecorder())
 | 
						c, _ := CreateTestContext(httptest.NewRecorder())
 | 
				
			||||||
	c.Request, _ = http.NewRequest("POST", "/", nil)
 | 
						c.Request, _ = http.NewRequest("POST", "/", nil)
 | 
				
			||||||
	c.Request.Header.Set("Content-Type", mw.FormDataContentType())
 | 
						c.Request.Header.Set("Content-Type", mw.FormDataContentType())
 | 
				
			||||||
	c.engine.MaxMultipartMemory = 8 << 20
 | 
						c.engine.MaxMultipartMemory = 8 << 20
 | 
				
			||||||
 | 
						assert.Panics(t, func() {
 | 
				
			||||||
		f, err := c.FormFile("file")
 | 
							f, err := c.FormFile("file")
 | 
				
			||||||
		assert.Error(t, err)
 | 
							assert.Error(t, err)
 | 
				
			||||||
		assert.Nil(t, f)
 | 
							assert.Nil(t, f)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -3,7 +3,6 @@
 | 
				
			|||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:build go1.19
 | 
					//go:build go1.19
 | 
				
			||||||
// +build go1.19
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package gin
 | 
					package gin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,6 @@
 | 
				
			|||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:build appengine
 | 
					//go:build appengine
 | 
				
			||||||
// +build appengine
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package gin
 | 
					package gin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -37,7 +37,7 @@ var errTestRender = errors.New("TestRender")
 | 
				
			|||||||
// Unit tests TODO
 | 
					// Unit tests TODO
 | 
				
			||||||
// func (c *Context) File(filepath string) {
 | 
					// func (c *Context) File(filepath string) {
 | 
				
			||||||
// func (c *Context) Negotiate(code int, config Negotiate) {
 | 
					// func (c *Context) Negotiate(code int, config Negotiate) {
 | 
				
			||||||
// BAD case: func (c *Context) Render(code int, render render.Render, obj ...interface{}) {
 | 
					// BAD case: func (c *Context) Render(code int, render render.Render, obj ...any) {
 | 
				
			||||||
// test that information is not leaked when reusing Contexts (using the Pool)
 | 
					// test that information is not leaked when reusing Contexts (using the Pool)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func createMultipartRequest() *http.Request {
 | 
					func createMultipartRequest() *http.Request {
 | 
				
			||||||
@ -2374,3 +2374,42 @@ func TestCreateTestContextWithRouteParams(t *testing.T) {
 | 
				
			|||||||
	assert.Equal(t, http.StatusOK, w.Code)
 | 
						assert.Equal(t, http.StatusOK, w.Code)
 | 
				
			||||||
	assert.Equal(t, "hello gin", w.Body.String())
 | 
						assert.Equal(t, "hello gin", w.Body.String())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type interceptedWriter struct {
 | 
				
			||||||
 | 
						ResponseWriter
 | 
				
			||||||
 | 
						b *bytes.Buffer
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (i interceptedWriter) WriteHeader(code int) {
 | 
				
			||||||
 | 
						i.Header().Del("X-Test")
 | 
				
			||||||
 | 
						i.ResponseWriter.WriteHeader(code)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestInterceptedHeader(t *testing.T) {
 | 
				
			||||||
 | 
						w := httptest.NewRecorder()
 | 
				
			||||||
 | 
						c, r := CreateTestContext(w)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r.Use(func(c *Context) {
 | 
				
			||||||
 | 
							i := interceptedWriter{
 | 
				
			||||||
 | 
								ResponseWriter: c.Writer,
 | 
				
			||||||
 | 
								b:              bytes.NewBuffer(nil),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							c.Writer = i
 | 
				
			||||||
 | 
							c.Next()
 | 
				
			||||||
 | 
							c.Header("X-Test", "overridden")
 | 
				
			||||||
 | 
							c.Writer = i.ResponseWriter
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						r.GET("/", func(c *Context) {
 | 
				
			||||||
 | 
							c.Header("X-Test", "original")
 | 
				
			||||||
 | 
							c.Header("X-Test-2", "present")
 | 
				
			||||||
 | 
							c.String(http.StatusOK, "hello world")
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						c.Request = httptest.NewRequest("GET", "/", nil)
 | 
				
			||||||
 | 
						r.HandleContext(c)
 | 
				
			||||||
 | 
						// Result() has headers frozen when WriteHeaderNow() has been called
 | 
				
			||||||
 | 
						// Compared to this time, this is when the response headers will be flushed
 | 
				
			||||||
 | 
						// As response is flushed on c.String, the Header cannot be set by the first
 | 
				
			||||||
 | 
						// middleware. Assert this
 | 
				
			||||||
 | 
						assert.Equal(t, "", w.Result().Header.Get("X-Test"))
 | 
				
			||||||
 | 
						assert.Equal(t, "present", w.Result().Header.Get("X-Test-2"))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								debug.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								debug.go
									
									
									
									
									
								
							@ -12,7 +12,7 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ginSupportMinGoVer = 16
 | 
					const ginSupportMinGoVer = 18
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IsDebugging returns true if the framework is running in debug mode.
 | 
					// IsDebugging returns true if the framework is running in debug mode.
 | 
				
			||||||
// Use SetMode(gin.ReleaseMode) to disable debug mode.
 | 
					// Use SetMode(gin.ReleaseMode) to disable debug mode.
 | 
				
			||||||
@ -67,7 +67,7 @@ func getMinVer(v string) (uint64, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func debugPrintWARNINGDefault() {
 | 
					func debugPrintWARNINGDefault() {
 | 
				
			||||||
	if v, e := getMinVer(runtime.Version()); e == nil && v < ginSupportMinGoVer {
 | 
						if v, e := getMinVer(runtime.Version()); e == nil && v < ginSupportMinGoVer {
 | 
				
			||||||
		debugPrint(`[WARNING] Now Gin requires Go 1.16+.
 | 
							debugPrint(`[WARNING] Now Gin requires Go 1.18+.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`)
 | 
					`)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// TODO
 | 
					// TODO
 | 
				
			||||||
// func debugRoute(httpMethod, absolutePath string, handlers HandlersChain) {
 | 
					// func debugRoute(httpMethod, absolutePath string, handlers HandlersChain) {
 | 
				
			||||||
// func debugPrint(format string, values ...interface{}) {
 | 
					// func debugPrint(format string, values ...any) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestIsDebugging(t *testing.T) {
 | 
					func TestIsDebugging(t *testing.T) {
 | 
				
			||||||
	SetMode(DebugMode)
 | 
						SetMode(DebugMode)
 | 
				
			||||||
@ -104,7 +104,7 @@ func TestDebugPrintWARNINGDefault(t *testing.T) {
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
	m, e := getMinVer(runtime.Version())
 | 
						m, e := getMinVer(runtime.Version())
 | 
				
			||||||
	if e == nil && m < ginSupportMinGoVer {
 | 
						if e == nil && m < ginSupportMinGoVer {
 | 
				
			||||||
		assert.Equal(t, "[GIN-debug] [WARNING] Now Gin requires Go 1.16+.\n\n[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.\n\n", re)
 | 
							assert.Equal(t, "[GIN-debug] [WARNING] Now Gin requires Go 1.18+.\n\n[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.\n\n", re)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		assert.Equal(t, "[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.\n\n", re)
 | 
							assert.Equal(t, "[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.\n\n", re)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@ import (
 | 
				
			|||||||
// BindWith binds the passed struct pointer using the specified binding engine.
 | 
					// BindWith binds the passed struct pointer using the specified binding engine.
 | 
				
			||||||
// See the binding package.
 | 
					// See the binding package.
 | 
				
			||||||
func (c *Context) BindWith(obj any, b binding.Binding) error {
 | 
					func (c *Context) BindWith(obj any, b binding.Binding) error {
 | 
				
			||||||
	log.Println(`BindWith(\"interface{}, binding.Binding\") error is going to
 | 
						log.Println(`BindWith(\"any, binding.Binding\") error is going to
 | 
				
			||||||
	be deprecated, please check issue #662 and either use MustBindWith() if you
 | 
						be deprecated, please check issue #662 and either use MustBindWith() if you
 | 
				
			||||||
	want HTTP 400 to be automatically returned if any error occur, or use
 | 
						want HTTP 400 to be automatically returned if any error occur, or use
 | 
				
			||||||
	ShouldBindWith() if you need to manage the error.`)
 | 
						ShouldBindWith() if you need to manage the error.`)
 | 
				
			||||||
 | 
				
			|||||||
@ -425,7 +425,7 @@ func main() {
 | 
				
			|||||||
  r.Use(gin.Logger())
 | 
					  r.Use(gin.Logger())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Recovery middleware recovers from any panics and writes a 500 if there was one.
 | 
					  // Recovery middleware recovers from any panics and writes a 500 if there was one.
 | 
				
			||||||
  r.Use(gin.CustomRecovery(func(c *gin.Context, recovered interface{}) {
 | 
					  r.Use(gin.CustomRecovery(func(c *gin.Context, recovered any) {
 | 
				
			||||||
    if err, ok := recovered.(string); ok {
 | 
					    if err, ok := recovered.(string); ok {
 | 
				
			||||||
      c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
 | 
					      c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -996,7 +996,7 @@ curl -X POST -v --form name=user --form "avatar=@./avatar.png" http://localhost:
 | 
				
			|||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
  r := gin.Default()
 | 
					  r := gin.Default()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // gin.H is a shortcut for map[string]interface{}
 | 
					  // gin.H is a shortcut for map[string]any
 | 
				
			||||||
  r.GET("/someJSON", func(c *gin.Context) {
 | 
					  r.GET("/someJSON", func(c *gin.Context) {
 | 
				
			||||||
    c.JSON(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
 | 
					    c.JSON(http.StatusOK, gin.H{"message": "hey", "status": http.StatusOK})
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
@ -1961,7 +1961,7 @@ func (customerBinding) Name() string {
 | 
				
			|||||||
  return "form"
 | 
					  return "form"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (customerBinding) Bind(req *http.Request, obj interface{}) error {
 | 
					func (customerBinding) Bind(req *http.Request, obj any) error {
 | 
				
			||||||
  if err := req.ParseForm(); err != nil {
 | 
					  if err := req.ParseForm(); err != nil {
 | 
				
			||||||
    return err
 | 
					    return err
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -1976,7 +1976,7 @@ func (customerBinding) Bind(req *http.Request, obj interface{}) error {
 | 
				
			|||||||
  return validate(obj)
 | 
					  return validate(obj)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func validate(obj interface{}) error {
 | 
					func validate(obj any) error {
 | 
				
			||||||
  if binding.Validator == nil {
 | 
					  if binding.Validator == nil {
 | 
				
			||||||
    return nil
 | 
					    return nil
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,6 @@
 | 
				
			|||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:build go_json
 | 
					//go:build go_json
 | 
				
			||||||
// +build go_json
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package json
 | 
					package json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,9 +3,6 @@
 | 
				
			|||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:build !jsoniter && !go_json && !(sonic && avx && (linux || windows || darwin) && amd64)
 | 
					//go:build !jsoniter && !go_json && !(sonic && avx && (linux || windows || darwin) && amd64)
 | 
				
			||||||
// +build !jsoniter
 | 
					 | 
				
			||||||
// +build !go_json
 | 
					 | 
				
			||||||
// +build !sonic !avx !linux,!windows,!darwin !amd64
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package json
 | 
					package json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,6 @@
 | 
				
			|||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:build jsoniter
 | 
					//go:build jsoniter
 | 
				
			||||||
// +build jsoniter
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package json
 | 
					package json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,10 +3,6 @@
 | 
				
			|||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:build sonic && avx && (linux || windows || darwin) && amd64
 | 
					//go:build sonic && avx && (linux || windows || darwin) && amd64
 | 
				
			||||||
// +build sonic
 | 
					 | 
				
			||||||
// +build avx
 | 
					 | 
				
			||||||
// +build linux windows darwin
 | 
					 | 
				
			||||||
// +build amd64
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package json
 | 
					package json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +0,0 @@
 | 
				
			|||||||
// Copyright 2021 Gin Core Team. All rights reserved.
 | 
					 | 
				
			||||||
// Use of this source code is governed by a MIT style
 | 
					 | 
				
			||||||
// license that can be found in the LICENSE file.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//go:build !go1.18
 | 
					 | 
				
			||||||
// +build !go1.18
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package render
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type any = interface{}
 | 
					 | 
				
			||||||
@ -3,7 +3,6 @@
 | 
				
			|||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:build !nomsgpack
 | 
					//go:build !nomsgpack
 | 
				
			||||||
// +build !nomsgpack
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package render
 | 
					package render
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,6 @@
 | 
				
			|||||||
// license that can be found in the LICENSE file.
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//go:build !nomsgpack
 | 
					//go:build !nomsgpack
 | 
				
			||||||
// +build !nomsgpack
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package render
 | 
					package render
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								testdata/protoexample/any.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								testdata/protoexample/any.go
									
									
									
									
										vendored
									
									
								
							@ -1,10 +0,0 @@
 | 
				
			|||||||
// Copyright 2021 Gin Core Team. All rights reserved.
 | 
					 | 
				
			||||||
// Use of this source code is governed by a MIT style
 | 
					 | 
				
			||||||
// license that can be found in the LICENSE file.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//go:build !go1.18
 | 
					 | 
				
			||||||
// +build !go1.18
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package protoexample
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type any = interface{}
 | 
					 | 
				
			||||||
							
								
								
									
										2
									
								
								utils.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								utils.go
									
									
									
									
									
								
							@ -50,7 +50,7 @@ func WrapH(h http.Handler) HandlerFunc {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// H is a shortcut for map[string]interface{}
 | 
					// H is a shortcut for map[string]any
 | 
				
			||||||
type H map[string]any
 | 
					type H map[string]any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MarshalXML allows type H to be used with xml.Marshal.
 | 
					// MarshalXML allows type H to be used with xml.Marshal.
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user