mirror of https://github.com/gin-gonic/gin.git
769 lines
18 KiB
Go
769 lines
18 KiB
Go
// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
|
|
// Use of this source code is governed by a MIT style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package gin
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"fmt"
|
|
"html/template"
|
|
"io"
|
|
"net"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"golang.org/x/net/http2"
|
|
)
|
|
|
|
func formatAsDate(t time.Time) string {
|
|
year, month, day := t.Date()
|
|
return fmt.Sprintf("%d/%02d/%02d", year, month, day)
|
|
}
|
|
|
|
func setupHTMLFiles(t *testing.T, mode string, tls bool, loadMethod func(*Engine)) *httptest.Server {
|
|
SetMode(mode)
|
|
defer SetMode(TestMode)
|
|
|
|
var router *Engine
|
|
captureOutput(t, func() {
|
|
router = New()
|
|
router.Delims("{[{", "}]}")
|
|
router.SetFuncMap(template.FuncMap{
|
|
"formatAsDate": formatAsDate,
|
|
})
|
|
loadMethod(router)
|
|
router.GET("/test", func(c *Context) {
|
|
c.HTML(http.StatusOK, "hello.tmpl", map[string]string{"name": "world"})
|
|
})
|
|
router.GET("/raw", func(c *Context) {
|
|
c.HTML(http.StatusOK, "raw.tmpl", map[string]any{
|
|
"now": time.Date(2017, 07, 01, 0, 0, 0, 0, time.UTC),
|
|
})
|
|
})
|
|
})
|
|
|
|
var ts *httptest.Server
|
|
|
|
if tls {
|
|
ts = httptest.NewTLSServer(router)
|
|
} else {
|
|
ts = httptest.NewServer(router)
|
|
}
|
|
|
|
return ts
|
|
}
|
|
|
|
func TestLoadHTMLGlobDebugMode(t *testing.T) {
|
|
ts := setupHTMLFiles(
|
|
t,
|
|
DebugMode,
|
|
false,
|
|
func(router *Engine) {
|
|
router.LoadHTMLGlob("./testdata/template/*")
|
|
},
|
|
)
|
|
defer ts.Close()
|
|
|
|
res, err := http.Get(ts.URL + "/test")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
resp, _ := io.ReadAll(res.Body)
|
|
assert.Equal(t, "<h1>Hello world</h1>", string(resp))
|
|
}
|
|
|
|
func TestH2c(t *testing.T) {
|
|
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
r := Default()
|
|
r.UseH2C = true
|
|
r.GET("/", func(c *Context) {
|
|
c.String(200, "<h1>Hello world</h1>")
|
|
})
|
|
go func() {
|
|
err := http.Serve(ln, r.Handler())
|
|
if err != nil {
|
|
t.Log(err)
|
|
}
|
|
}()
|
|
defer ln.Close()
|
|
|
|
url := "http://" + ln.Addr().String() + "/"
|
|
|
|
httpClient := http.Client{
|
|
Transport: &http2.Transport{
|
|
AllowHTTP: true,
|
|
DialTLS: func(netw, addr string, cfg *tls.Config) (net.Conn, error) {
|
|
return net.Dial(netw, addr)
|
|
},
|
|
},
|
|
}
|
|
|
|
res, err := httpClient.Get(url)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
resp, _ := io.ReadAll(res.Body)
|
|
assert.Equal(t, "<h1>Hello world</h1>", string(resp))
|
|
}
|
|
|
|
func TestLoadHTMLGlobTestMode(t *testing.T) {
|
|
ts := setupHTMLFiles(
|
|
t,
|
|
TestMode,
|
|
false,
|
|
func(router *Engine) {
|
|
router.LoadHTMLGlob("./testdata/template/*")
|
|
},
|
|
)
|
|
defer ts.Close()
|
|
|
|
res, err := http.Get(ts.URL + "/test")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
resp, _ := io.ReadAll(res.Body)
|
|
assert.Equal(t, "<h1>Hello world</h1>", string(resp))
|
|
}
|
|
|
|
func TestLoadHTMLGlobReleaseMode(t *testing.T) {
|
|
ts := setupHTMLFiles(
|
|
t,
|
|
ReleaseMode,
|
|
false,
|
|
func(router *Engine) {
|
|
router.LoadHTMLGlob("./testdata/template/*")
|
|
},
|
|
)
|
|
defer ts.Close()
|
|
|
|
res, err := http.Get(ts.URL + "/test")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
resp, _ := io.ReadAll(res.Body)
|
|
assert.Equal(t, "<h1>Hello world</h1>", string(resp))
|
|
}
|
|
|
|
func TestLoadHTMLGlobUsingTLS(t *testing.T) {
|
|
ts := setupHTMLFiles(
|
|
t,
|
|
DebugMode,
|
|
true,
|
|
func(router *Engine) {
|
|
router.LoadHTMLGlob("./testdata/template/*")
|
|
},
|
|
)
|
|
defer ts.Close()
|
|
|
|
// Use InsecureSkipVerify for avoiding `x509: certificate signed by unknown authority` error
|
|
tr := &http.Transport{
|
|
TLSClientConfig: &tls.Config{
|
|
InsecureSkipVerify: true,
|
|
},
|
|
}
|
|
client := &http.Client{Transport: tr}
|
|
res, err := client.Get(ts.URL + "/test")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
resp, _ := io.ReadAll(res.Body)
|
|
assert.Equal(t, "<h1>Hello world</h1>", string(resp))
|
|
}
|
|
|
|
func TestLoadHTMLGlobFromFuncMap(t *testing.T) {
|
|
ts := setupHTMLFiles(
|
|
t,
|
|
DebugMode,
|
|
false,
|
|
func(router *Engine) {
|
|
router.LoadHTMLGlob("./testdata/template/*")
|
|
},
|
|
)
|
|
defer ts.Close()
|
|
|
|
res, err := http.Get(ts.URL + "/raw")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
resp, _ := io.ReadAll(res.Body)
|
|
assert.Equal(t, "Date: 2017/07/01", string(resp))
|
|
}
|
|
|
|
func init() {
|
|
SetMode(TestMode)
|
|
}
|
|
|
|
func TestCreateEngine(t *testing.T) {
|
|
router := New()
|
|
assert.Equal(t, "/", router.basePath)
|
|
assert.Equal(t, router.engine, router)
|
|
assert.Empty(t, router.Handlers)
|
|
}
|
|
|
|
func TestLoadHTMLFilesTestMode(t *testing.T) {
|
|
ts := setupHTMLFiles(
|
|
t,
|
|
TestMode,
|
|
false,
|
|
func(router *Engine) {
|
|
router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl")
|
|
},
|
|
)
|
|
defer ts.Close()
|
|
|
|
res, err := http.Get(ts.URL + "/test")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
resp, _ := io.ReadAll(res.Body)
|
|
assert.Equal(t, "<h1>Hello world</h1>", string(resp))
|
|
}
|
|
|
|
func TestLoadHTMLFilesDebugMode(t *testing.T) {
|
|
ts := setupHTMLFiles(
|
|
t,
|
|
DebugMode,
|
|
false,
|
|
func(router *Engine) {
|
|
router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl")
|
|
},
|
|
)
|
|
defer ts.Close()
|
|
|
|
res, err := http.Get(ts.URL + "/test")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
resp, _ := io.ReadAll(res.Body)
|
|
assert.Equal(t, "<h1>Hello world</h1>", string(resp))
|
|
}
|
|
|
|
func TestLoadHTMLFilesReleaseMode(t *testing.T) {
|
|
ts := setupHTMLFiles(
|
|
t,
|
|
ReleaseMode,
|
|
false,
|
|
func(router *Engine) {
|
|
router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl")
|
|
},
|
|
)
|
|
defer ts.Close()
|
|
|
|
res, err := http.Get(ts.URL + "/test")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
resp, _ := io.ReadAll(res.Body)
|
|
assert.Equal(t, "<h1>Hello world</h1>", string(resp))
|
|
}
|
|
|
|
func TestLoadHTMLFilesUsingTLS(t *testing.T) {
|
|
ts := setupHTMLFiles(
|
|
t,
|
|
TestMode,
|
|
true,
|
|
func(router *Engine) {
|
|
router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl")
|
|
},
|
|
)
|
|
defer ts.Close()
|
|
|
|
// Use InsecureSkipVerify for avoiding `x509: certificate signed by unknown authority` error
|
|
tr := &http.Transport{
|
|
TLSClientConfig: &tls.Config{
|
|
InsecureSkipVerify: true,
|
|
},
|
|
}
|
|
client := &http.Client{Transport: tr}
|
|
res, err := client.Get(ts.URL + "/test")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
resp, _ := io.ReadAll(res.Body)
|
|
assert.Equal(t, "<h1>Hello world</h1>", string(resp))
|
|
}
|
|
|
|
func TestLoadHTMLFilesFuncMap(t *testing.T) {
|
|
ts := setupHTMLFiles(
|
|
t,
|
|
TestMode,
|
|
false,
|
|
func(router *Engine) {
|
|
router.LoadHTMLFiles("./testdata/template/hello.tmpl", "./testdata/template/raw.tmpl")
|
|
},
|
|
)
|
|
defer ts.Close()
|
|
|
|
res, err := http.Get(ts.URL + "/raw")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
resp, _ := io.ReadAll(res.Body)
|
|
assert.Equal(t, "Date: 2017/07/01", string(resp))
|
|
}
|
|
|
|
func TestAddRoute(t *testing.T) {
|
|
router := New()
|
|
router.addRoute(http.MethodGet, "/", HandlersChain{func(_ *Context) {}})
|
|
|
|
assert.Len(t, router.trees, 1)
|
|
assert.NotNil(t, router.trees.get(http.MethodGet))
|
|
assert.Nil(t, router.trees.get(http.MethodPost))
|
|
|
|
router.addRoute(http.MethodPost, "/", HandlersChain{func(_ *Context) {}})
|
|
|
|
assert.Len(t, router.trees, 2)
|
|
assert.NotNil(t, router.trees.get(http.MethodGet))
|
|
assert.NotNil(t, router.trees.get(http.MethodPost))
|
|
|
|
router.addRoute(http.MethodPost, "/post", HandlersChain{func(_ *Context) {}})
|
|
assert.Len(t, router.trees, 2)
|
|
}
|
|
|
|
func TestAddRouteFails(t *testing.T) {
|
|
router := New()
|
|
assert.Panics(t, func() { router.addRoute("", "/", HandlersChain{func(_ *Context) {}}) })
|
|
assert.Panics(t, func() { router.addRoute(http.MethodGet, "a", HandlersChain{func(_ *Context) {}}) })
|
|
assert.Panics(t, func() { router.addRoute(http.MethodGet, "/", HandlersChain{}) })
|
|
|
|
router.addRoute(http.MethodPost, "/post", HandlersChain{func(_ *Context) {}})
|
|
assert.Panics(t, func() {
|
|
router.addRoute(http.MethodPost, "/post", HandlersChain{func(_ *Context) {}})
|
|
})
|
|
}
|
|
|
|
func TestCreateDefaultRouter(t *testing.T) {
|
|
router := Default()
|
|
assert.Len(t, router.Handlers, 2)
|
|
}
|
|
|
|
func TestNoRouteWithoutGlobalHandlers(t *testing.T) {
|
|
var middleware0 HandlerFunc = func(c *Context) {}
|
|
var middleware1 HandlerFunc = func(c *Context) {}
|
|
|
|
router := New()
|
|
|
|
router.NoRoute(middleware0)
|
|
assert.Nil(t, router.Handlers)
|
|
assert.Len(t, router.noRoute, 1)
|
|
assert.Len(t, router.allNoRoute, 1)
|
|
compareFunc(t, router.noRoute[0], middleware0)
|
|
compareFunc(t, router.allNoRoute[0], middleware0)
|
|
|
|
router.NoRoute(middleware1, middleware0)
|
|
assert.Len(t, router.noRoute, 2)
|
|
assert.Len(t, router.allNoRoute, 2)
|
|
compareFunc(t, router.noRoute[0], middleware1)
|
|
compareFunc(t, router.allNoRoute[0], middleware1)
|
|
compareFunc(t, router.noRoute[1], middleware0)
|
|
compareFunc(t, router.allNoRoute[1], middleware0)
|
|
}
|
|
|
|
func TestNoRouteWithGlobalHandlers(t *testing.T) {
|
|
var middleware0 HandlerFunc = func(c *Context) {}
|
|
var middleware1 HandlerFunc = func(c *Context) {}
|
|
var middleware2 HandlerFunc = func(c *Context) {}
|
|
|
|
router := New()
|
|
router.Use(middleware2)
|
|
|
|
router.NoRoute(middleware0)
|
|
assert.Len(t, router.allNoRoute, 2)
|
|
assert.Len(t, router.Handlers, 1)
|
|
assert.Len(t, router.noRoute, 1)
|
|
|
|
compareFunc(t, router.Handlers[0], middleware2)
|
|
compareFunc(t, router.noRoute[0], middleware0)
|
|
compareFunc(t, router.allNoRoute[0], middleware2)
|
|
compareFunc(t, router.allNoRoute[1], middleware0)
|
|
|
|
router.Use(middleware1)
|
|
assert.Len(t, router.allNoRoute, 3)
|
|
assert.Len(t, router.Handlers, 2)
|
|
assert.Len(t, router.noRoute, 1)
|
|
|
|
compareFunc(t, router.Handlers[0], middleware2)
|
|
compareFunc(t, router.Handlers[1], middleware1)
|
|
compareFunc(t, router.noRoute[0], middleware0)
|
|
compareFunc(t, router.allNoRoute[0], middleware2)
|
|
compareFunc(t, router.allNoRoute[1], middleware1)
|
|
compareFunc(t, router.allNoRoute[2], middleware0)
|
|
}
|
|
|
|
func TestNoMethodWithoutGlobalHandlers(t *testing.T) {
|
|
var middleware0 HandlerFunc = func(c *Context) {}
|
|
var middleware1 HandlerFunc = func(c *Context) {}
|
|
|
|
router := New()
|
|
|
|
router.NoMethod(middleware0)
|
|
assert.Empty(t, router.Handlers)
|
|
assert.Len(t, router.noMethod, 1)
|
|
assert.Len(t, router.allNoMethod, 1)
|
|
compareFunc(t, router.noMethod[0], middleware0)
|
|
compareFunc(t, router.allNoMethod[0], middleware0)
|
|
|
|
router.NoMethod(middleware1, middleware0)
|
|
assert.Len(t, router.noMethod, 2)
|
|
assert.Len(t, router.allNoMethod, 2)
|
|
compareFunc(t, router.noMethod[0], middleware1)
|
|
compareFunc(t, router.allNoMethod[0], middleware1)
|
|
compareFunc(t, router.noMethod[1], middleware0)
|
|
compareFunc(t, router.allNoMethod[1], middleware0)
|
|
}
|
|
|
|
func TestRebuild404Handlers(t *testing.T) {
|
|
}
|
|
|
|
func TestNoMethodWithGlobalHandlers(t *testing.T) {
|
|
var middleware0 HandlerFunc = func(c *Context) {}
|
|
var middleware1 HandlerFunc = func(c *Context) {}
|
|
var middleware2 HandlerFunc = func(c *Context) {}
|
|
|
|
router := New()
|
|
router.Use(middleware2)
|
|
|
|
router.NoMethod(middleware0)
|
|
assert.Len(t, router.allNoMethod, 2)
|
|
assert.Len(t, router.Handlers, 1)
|
|
assert.Len(t, router.noMethod, 1)
|
|
|
|
compareFunc(t, router.Handlers[0], middleware2)
|
|
compareFunc(t, router.noMethod[0], middleware0)
|
|
compareFunc(t, router.allNoMethod[0], middleware2)
|
|
compareFunc(t, router.allNoMethod[1], middleware0)
|
|
|
|
router.Use(middleware1)
|
|
assert.Len(t, router.allNoMethod, 3)
|
|
assert.Len(t, router.Handlers, 2)
|
|
assert.Len(t, router.noMethod, 1)
|
|
|
|
compareFunc(t, router.Handlers[0], middleware2)
|
|
compareFunc(t, router.Handlers[1], middleware1)
|
|
compareFunc(t, router.noMethod[0], middleware0)
|
|
compareFunc(t, router.allNoMethod[0], middleware2)
|
|
compareFunc(t, router.allNoMethod[1], middleware1)
|
|
compareFunc(t, router.allNoMethod[2], middleware0)
|
|
}
|
|
|
|
func compareFunc(t *testing.T, a, b any) {
|
|
sf1 := reflect.ValueOf(a)
|
|
sf2 := reflect.ValueOf(b)
|
|
if sf1.Pointer() != sf2.Pointer() {
|
|
t.Error("different functions")
|
|
}
|
|
}
|
|
|
|
func TestListOfRoutes(t *testing.T) {
|
|
router := New()
|
|
router.GET("/favicon.ico", handlerTest1)
|
|
router.GET("/", handlerTest1)
|
|
group := router.Group("/users")
|
|
{
|
|
group.GET("/", handlerTest2)
|
|
group.GET("/:id", handlerTest1)
|
|
group.POST("/:id", handlerTest2)
|
|
}
|
|
router.Static("/static", ".")
|
|
|
|
list := router.Routes()
|
|
|
|
assert.Len(t, list, 7)
|
|
assertRoutePresent(t, list, RouteInfo{
|
|
Method: http.MethodGet,
|
|
Path: "/favicon.ico",
|
|
Handler: "^(.*/vendor/)?github.com/gin-gonic/gin.handlerTest1$",
|
|
})
|
|
assertRoutePresent(t, list, RouteInfo{
|
|
Method: http.MethodGet,
|
|
Path: "/",
|
|
Handler: "^(.*/vendor/)?github.com/gin-gonic/gin.handlerTest1$",
|
|
})
|
|
assertRoutePresent(t, list, RouteInfo{
|
|
Method: http.MethodGet,
|
|
Path: "/users/",
|
|
Handler: "^(.*/vendor/)?github.com/gin-gonic/gin.handlerTest2$",
|
|
})
|
|
assertRoutePresent(t, list, RouteInfo{
|
|
Method: http.MethodGet,
|
|
Path: "/users/:id",
|
|
Handler: "^(.*/vendor/)?github.com/gin-gonic/gin.handlerTest1$",
|
|
})
|
|
assertRoutePresent(t, list, RouteInfo{
|
|
Method: http.MethodPost,
|
|
Path: "/users/:id",
|
|
Handler: "^(.*/vendor/)?github.com/gin-gonic/gin.handlerTest2$",
|
|
})
|
|
}
|
|
|
|
func TestEngineHandleContext(t *testing.T) {
|
|
r := New()
|
|
r.GET("/", func(c *Context) {
|
|
c.Request.URL.Path = "/v2"
|
|
r.HandleContext(c)
|
|
})
|
|
v2 := r.Group("/v2")
|
|
{
|
|
v2.GET("/", func(c *Context) {})
|
|
}
|
|
|
|
assert.NotPanics(t, func() {
|
|
w := PerformRequest(r, http.MethodGet, "/")
|
|
assert.Equal(t, 301, w.Code)
|
|
})
|
|
}
|
|
|
|
func TestEngineHandleContextManyReEntries(t *testing.T) {
|
|
expectValue := 10000
|
|
|
|
var handlerCounter, middlewareCounter int64
|
|
|
|
r := New()
|
|
r.Use(func(c *Context) {
|
|
atomic.AddInt64(&middlewareCounter, 1)
|
|
})
|
|
r.GET("/:count", func(c *Context) {
|
|
countStr := c.Param("count")
|
|
count, err := strconv.Atoi(countStr)
|
|
require.NoError(t, err)
|
|
|
|
n, err := c.Writer.Write([]byte("."))
|
|
require.NoError(t, err)
|
|
assert.Equal(t, 1, n)
|
|
|
|
switch {
|
|
case count > 0:
|
|
c.Request.URL.Path = "/" + strconv.Itoa(count-1)
|
|
r.HandleContext(c)
|
|
}
|
|
}, func(c *Context) {
|
|
atomic.AddInt64(&handlerCounter, 1)
|
|
})
|
|
|
|
assert.NotPanics(t, func() {
|
|
w := PerformRequest(r, http.MethodGet, "/"+strconv.Itoa(expectValue-1)) // include 0 value
|
|
assert.Equal(t, 200, w.Code)
|
|
assert.Equal(t, expectValue, w.Body.Len())
|
|
})
|
|
|
|
assert.Equal(t, int64(expectValue), handlerCounter)
|
|
assert.Equal(t, int64(expectValue), middlewareCounter)
|
|
}
|
|
|
|
func TestPrepareTrustedCIRDsWith(t *testing.T) {
|
|
r := New()
|
|
|
|
// valid ipv4 cidr
|
|
{
|
|
expectedTrustedCIDRs := []*net.IPNet{parseCIDR("0.0.0.0/0")}
|
|
err := r.SetTrustedProxies([]string{"0.0.0.0/0"})
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, expectedTrustedCIDRs, r.trustedCIDRs)
|
|
}
|
|
|
|
// invalid ipv4 cidr
|
|
{
|
|
err := r.SetTrustedProxies([]string{"192.168.1.33/33"})
|
|
|
|
require.Error(t, err)
|
|
}
|
|
|
|
// valid ipv4 address
|
|
{
|
|
expectedTrustedCIDRs := []*net.IPNet{parseCIDR("192.168.1.33/32")}
|
|
|
|
err := r.SetTrustedProxies([]string{"192.168.1.33"})
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, expectedTrustedCIDRs, r.trustedCIDRs)
|
|
}
|
|
|
|
// invalid ipv4 address
|
|
{
|
|
err := r.SetTrustedProxies([]string{"192.168.1.256"})
|
|
|
|
require.Error(t, err)
|
|
}
|
|
|
|
// valid ipv6 address
|
|
{
|
|
expectedTrustedCIDRs := []*net.IPNet{parseCIDR("2002:0000:0000:1234:abcd:ffff:c0a8:0101/128")}
|
|
err := r.SetTrustedProxies([]string{"2002:0000:0000:1234:abcd:ffff:c0a8:0101"})
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, expectedTrustedCIDRs, r.trustedCIDRs)
|
|
}
|
|
|
|
// invalid ipv6 address
|
|
{
|
|
err := r.SetTrustedProxies([]string{"gggg:0000:0000:1234:abcd:ffff:c0a8:0101"})
|
|
|
|
require.Error(t, err)
|
|
}
|
|
|
|
// valid ipv6 cidr
|
|
{
|
|
expectedTrustedCIDRs := []*net.IPNet{parseCIDR("::/0")}
|
|
err := r.SetTrustedProxies([]string{"::/0"})
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, expectedTrustedCIDRs, r.trustedCIDRs)
|
|
}
|
|
|
|
// invalid ipv6 cidr
|
|
{
|
|
err := r.SetTrustedProxies([]string{"gggg:0000:0000:1234:abcd:ffff:c0a8:0101/129"})
|
|
|
|
require.Error(t, err)
|
|
}
|
|
|
|
// valid combination
|
|
{
|
|
expectedTrustedCIDRs := []*net.IPNet{
|
|
parseCIDR("::/0"),
|
|
parseCIDR("192.168.0.0/16"),
|
|
parseCIDR("172.16.0.1/32"),
|
|
}
|
|
err := r.SetTrustedProxies([]string{
|
|
"::/0",
|
|
"192.168.0.0/16",
|
|
"172.16.0.1",
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
assert.Equal(t, expectedTrustedCIDRs, r.trustedCIDRs)
|
|
}
|
|
|
|
// invalid combination
|
|
{
|
|
err := r.SetTrustedProxies([]string{
|
|
"::/0",
|
|
"192.168.0.0/16",
|
|
"172.16.0.256",
|
|
})
|
|
|
|
require.Error(t, err)
|
|
}
|
|
|
|
// nil value
|
|
{
|
|
err := r.SetTrustedProxies(nil)
|
|
|
|
assert.Nil(t, r.trustedCIDRs)
|
|
require.NoError(t, err)
|
|
}
|
|
}
|
|
|
|
func parseCIDR(cidr string) *net.IPNet {
|
|
_, parsedCIDR, err := net.ParseCIDR(cidr)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
return parsedCIDR
|
|
}
|
|
|
|
func assertRoutePresent(t *testing.T, gotRoutes RoutesInfo, wantRoute RouteInfo) {
|
|
for _, gotRoute := range gotRoutes {
|
|
if gotRoute.Path == wantRoute.Path && gotRoute.Method == wantRoute.Method {
|
|
assert.Regexp(t, wantRoute.Handler, gotRoute.Handler)
|
|
return
|
|
}
|
|
}
|
|
t.Errorf("route not found: %v", wantRoute)
|
|
}
|
|
|
|
func handlerTest1(c *Context) {}
|
|
func handlerTest2(c *Context) {}
|
|
|
|
func TestNewOptionFunc(t *testing.T) {
|
|
var fc = func(e *Engine) {
|
|
e.GET("/test1", handlerTest1)
|
|
e.GET("/test2", handlerTest2)
|
|
|
|
e.Use(func(c *Context) {
|
|
c.Next()
|
|
})
|
|
}
|
|
|
|
r := New(fc)
|
|
|
|
routes := r.Routes()
|
|
assertRoutePresent(t, routes, RouteInfo{Path: "/test1", Method: http.MethodGet, Handler: "github.com/gin-gonic/gin.handlerTest1"})
|
|
assertRoutePresent(t, routes, RouteInfo{Path: "/test2", Method: http.MethodGet, Handler: "github.com/gin-gonic/gin.handlerTest2"})
|
|
}
|
|
|
|
func TestWithOptionFunc(t *testing.T) {
|
|
r := New()
|
|
|
|
r.With(func(e *Engine) {
|
|
e.GET("/test1", handlerTest1)
|
|
e.GET("/test2", handlerTest2)
|
|
|
|
e.Use(func(c *Context) {
|
|
c.Next()
|
|
})
|
|
})
|
|
|
|
routes := r.Routes()
|
|
assertRoutePresent(t, routes, RouteInfo{Path: "/test1", Method: http.MethodGet, Handler: "github.com/gin-gonic/gin.handlerTest1"})
|
|
assertRoutePresent(t, routes, RouteInfo{Path: "/test2", Method: http.MethodGet, Handler: "github.com/gin-gonic/gin.handlerTest2"})
|
|
}
|
|
|
|
type Birthday string
|
|
|
|
func (b *Birthday) UnmarshalParam(param string) error {
|
|
*b = Birthday(strings.Replace(param, "-", "/", -1))
|
|
return nil
|
|
}
|
|
|
|
func TestCustomUnmarshalStruct(t *testing.T) {
|
|
route := Default()
|
|
var request struct {
|
|
Birthday Birthday `form:"birthday"`
|
|
}
|
|
route.GET("/test", func(ctx *Context) {
|
|
_ = ctx.BindQuery(&request)
|
|
ctx.JSON(200, request.Birthday)
|
|
})
|
|
req := httptest.NewRequest(http.MethodGet, "/test?birthday=2000-01-01", nil)
|
|
w := httptest.NewRecorder()
|
|
route.ServeHTTP(w, req)
|
|
assert.Equal(t, 200, w.Code)
|
|
assert.Equal(t, `"2000/01/01"`, w.Body.String())
|
|
}
|
|
|
|
// Test the fix for https://github.com/gin-gonic/gin/issues/4002
|
|
func TestMethodNotAllowedNoRoute(t *testing.T) {
|
|
g := New()
|
|
g.HandleMethodNotAllowed = true
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
|
resp := httptest.NewRecorder()
|
|
assert.NotPanics(t, func() { g.ServeHTTP(resp, req) })
|
|
assert.Equal(t, http.StatusNotFound, resp.Code)
|
|
}
|