Compare commits

...

7 Commits

Author SHA1 Message Date
p8bin 52e473cff2
Merge 8e66616db7 into e46bd52185 2024-11-19 13:32:03 +00:00
haesuo566 e46bd52185
refactor(context): add an optional permission parameter to the SaveUploadedFile method (#4068) (#4088)
Co-authored-by: hso <hso@trinitysoft.co.kr>
2024-11-15 23:54:06 +08:00
Matthieu MOREL e8d34d053f
ci(lint): enable usestdlibvars linter (#4091)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2024-11-15 23:52:16 +08:00
Matthieu MOREL 02c1144f31
ci(lint): enable perfsprint linter (#4090)
Signed-off-by: Matthieu MOREL <matthieu.morel35@gmail.com>
2024-11-15 23:51:12 +08:00
Bo-Yi Wu f875d87283
chore(context): test context initialization and handler logic (#4087)
* enhance code imported by #3413

if it needs to check if the handler is nil, tie c.index shall
always ++

* test: refactor test context initialization and handler logic

- Remove an empty line in `TestContextInitQueryCache`
- Add `TestContextNext` function with tests for `Next` method behavior with no handlers, one handler, and multiple handlers

Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>

---------

Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
Co-authored-by: zjj <zhong2plus@gmail.com>
2024-11-15 23:49:08 +08:00
Konovalov Maxim c8a3adc657
refactor(context): simplify "GetType()" functions (#4080)
This PR introduces a generic function, getTyped[T any], to simplify value retrieval in the Context struct. It replaces repetitive type assertions in the GetString  GetBool etc. methods.

Co-authored-by: Maksim Konovalov <maksim.konovalov@vk.team>
2024-10-29 23:24:53 +08:00
nibi8 8e66616db7 Error parser 2022-05-11 21:56:28 +03:00
26 changed files with 795 additions and 469 deletions

View File

@ -16,8 +16,10 @@ linters:
- nakedret
- nilerr
- nolintlint
- perfsprint
- revive
- testifylint
- usestdlibvars
- wastedassign
linters-settings:
@ -34,6 +36,13 @@ linters-settings:
- G112
- G201
- G203
perfsprint:
err-error: true
errorf: true
fiximports: true
int-conversion: true
sprintf1: true
strconcat: true
testifylint:
enable-all: true

View File

@ -90,7 +90,7 @@ func TestBasicAuthSucceed(t *testing.T) {
})
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/login", nil)
req, _ := http.NewRequest(http.MethodGet, "/login", nil)
req.Header.Set("Authorization", authorizationHeader("admin", "password"))
router.ServeHTTP(w, req)
@ -109,7 +109,7 @@ func TestBasicAuth401(t *testing.T) {
})
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/login", nil)
req, _ := http.NewRequest(http.MethodGet, "/login", nil)
req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte("admin:password")))
router.ServeHTTP(w, req)
@ -129,7 +129,7 @@ func TestBasicAuth401WithCustomRealm(t *testing.T) {
})
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/login", nil)
req, _ := http.NewRequest(http.MethodGet, "/login", nil)
req.Header.Set("Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte("admin:password")))
router.ServeHTTP(w, req)
@ -147,7 +147,7 @@ func TestBasicAuthForProxySucceed(t *testing.T) {
})
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/test", nil)
req, _ := http.NewRequest(http.MethodGet, "/test", nil)
req.Header.Set("Proxy-Authorization", authorizationHeader("admin", "password"))
router.ServeHTTP(w, req)
@ -166,7 +166,7 @@ func TestBasicAuthForProxy407(t *testing.T) {
})
w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", "/test", nil)
req, _ := http.NewRequest(http.MethodGet, "/test", nil)
req.Header.Set("Proxy-Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte("admin:password")))
router.ServeHTTP(w, req)

View File

@ -14,21 +14,21 @@ import (
func BenchmarkOneRoute(B *testing.B) {
router := New()
router.GET("/ping", func(c *Context) {})
runRequest(B, router, "GET", "/ping")
runRequest(B, router, http.MethodGet, "/ping")
}
func BenchmarkRecoveryMiddleware(B *testing.B) {
router := New()
router.Use(Recovery())
router.GET("/", func(c *Context) {})
runRequest(B, router, "GET", "/")
runRequest(B, router, http.MethodGet, "/")
}
func BenchmarkLoggerMiddleware(B *testing.B) {
router := New()
router.Use(LoggerWithWriter(newMockWriter()))
router.GET("/", func(c *Context) {})
runRequest(B, router, "GET", "/")
runRequest(B, router, http.MethodGet, "/")
}
func BenchmarkManyHandlers(B *testing.B) {
@ -37,7 +37,7 @@ func BenchmarkManyHandlers(B *testing.B) {
router.Use(func(c *Context) {})
router.Use(func(c *Context) {})
router.GET("/ping", func(c *Context) {})
runRequest(B, router, "GET", "/ping")
runRequest(B, router, http.MethodGet, "/ping")
}
func Benchmark5Params(B *testing.B) {
@ -45,7 +45,7 @@ func Benchmark5Params(B *testing.B) {
router := New()
router.Use(func(c *Context) {})
router.GET("/param/:param1/:params2/:param3/:param4/:param5", func(c *Context) {})
runRequest(B, router, "GET", "/param/path/to/parameter/john/12345")
runRequest(B, router, http.MethodGet, "/param/path/to/parameter/john/12345")
}
func BenchmarkOneRouteJSON(B *testing.B) {
@ -56,7 +56,7 @@ func BenchmarkOneRouteJSON(B *testing.B) {
router.GET("/json", func(c *Context) {
c.JSON(http.StatusOK, data)
})
runRequest(B, router, "GET", "/json")
runRequest(B, router, http.MethodGet, "/json")
}
func BenchmarkOneRouteHTML(B *testing.B) {
@ -68,7 +68,7 @@ func BenchmarkOneRouteHTML(B *testing.B) {
router.GET("/html", func(c *Context) {
c.HTML(http.StatusOK, "index", "hola")
})
runRequest(B, router, "GET", "/html")
runRequest(B, router, http.MethodGet, "/html")
}
func BenchmarkOneRouteSet(B *testing.B) {
@ -76,7 +76,7 @@ func BenchmarkOneRouteSet(B *testing.B) {
router.GET("/ping", func(c *Context) {
c.Set("key", "value")
})
runRequest(B, router, "GET", "/ping")
runRequest(B, router, http.MethodGet, "/ping")
}
func BenchmarkOneRouteString(B *testing.B) {
@ -84,13 +84,13 @@ func BenchmarkOneRouteString(B *testing.B) {
router.GET("/text", func(c *Context) {
c.String(http.StatusOK, "this is a plain text")
})
runRequest(B, router, "GET", "/text")
runRequest(B, router, http.MethodGet, "/text")
}
func BenchmarkManyRoutesFist(B *testing.B) {
router := New()
router.Any("/ping", func(c *Context) {})
runRequest(B, router, "GET", "/ping")
runRequest(B, router, http.MethodGet, "/ping")
}
func BenchmarkManyRoutesLast(B *testing.B) {
@ -103,7 +103,7 @@ func Benchmark404(B *testing.B) {
router := New()
router.Any("/something", func(c *Context) {})
router.NoRoute(func(c *Context) {})
runRequest(B, router, "GET", "/ping")
runRequest(B, router, http.MethodGet, "/ping")
}
func Benchmark404Many(B *testing.B) {
@ -118,7 +118,7 @@ func Benchmark404Many(B *testing.B) {
router.GET("/user/:id/:mode", func(c *Context) {})
router.NoRoute(func(c *Context) {})
runRequest(B, router, "GET", "/viewfake")
runRequest(B, router, http.MethodGet, "/viewfake")
}
type mockWriter struct {

View File

@ -8,6 +8,7 @@ package binding
import (
"bytes"
"net/http"
"testing"
"github.com/stretchr/testify/assert"
@ -39,20 +40,20 @@ func testMsgPackBodyBinding(t *testing.T, b Binding, name, path, badPath, body,
assert.Equal(t, name, b.Name())
obj := FooStruct{}
req := requestWithBody("POST", path, body)
req := requestWithBody(http.MethodPost, path, body)
req.Header.Add("Content-Type", MIMEMSGPACK)
err := b.Bind(req, &obj)
require.NoError(t, err)
assert.Equal(t, "bar", obj.Foo)
obj = FooStruct{}
req = requestWithBody("POST", badPath, badBody)
req = requestWithBody(http.MethodPost, badPath, badBody)
req.Header.Add("Content-Type", MIMEMSGPACK)
err = MsgPack.Bind(req, &obj)
require.Error(t, err)
}
func TestBindingDefaultMsgPack(t *testing.T) {
assert.Equal(t, MsgPack, Default("POST", MIMEMSGPACK))
assert.Equal(t, MsgPack, Default("PUT", MIMEMSGPACK2))
assert.Equal(t, MsgPack, Default(http.MethodPost, MIMEMSGPACK))
assert.Equal(t, MsgPack, Default(http.MethodPut, MIMEMSGPACK2))
}

View File

@ -145,31 +145,31 @@ type FooStructForMapPtrType struct {
}
func TestBindingDefault(t *testing.T) {
assert.Equal(t, Form, Default("GET", ""))
assert.Equal(t, Form, Default("GET", MIMEJSON))
assert.Equal(t, Form, Default(http.MethodGet, ""))
assert.Equal(t, Form, Default(http.MethodGet, MIMEJSON))
assert.Equal(t, JSON, Default("POST", MIMEJSON))
assert.Equal(t, JSON, Default("PUT", MIMEJSON))
assert.Equal(t, JSON, Default(http.MethodPost, MIMEJSON))
assert.Equal(t, JSON, Default(http.MethodPut, MIMEJSON))
assert.Equal(t, XML, Default("POST", MIMEXML))
assert.Equal(t, XML, Default("PUT", MIMEXML2))
assert.Equal(t, XML, Default(http.MethodPost, MIMEXML))
assert.Equal(t, XML, Default(http.MethodPut, MIMEXML2))
assert.Equal(t, Form, Default("POST", MIMEPOSTForm))
assert.Equal(t, Form, Default("PUT", MIMEPOSTForm))
assert.Equal(t, Form, Default(http.MethodPost, MIMEPOSTForm))
assert.Equal(t, Form, Default(http.MethodPut, MIMEPOSTForm))
assert.Equal(t, FormMultipart, Default("POST", MIMEMultipartPOSTForm))
assert.Equal(t, FormMultipart, Default("PUT", MIMEMultipartPOSTForm))
assert.Equal(t, FormMultipart, Default(http.MethodPost, MIMEMultipartPOSTForm))
assert.Equal(t, FormMultipart, Default(http.MethodPut, MIMEMultipartPOSTForm))
assert.Equal(t, ProtoBuf, Default("POST", MIMEPROTOBUF))
assert.Equal(t, ProtoBuf, Default("PUT", MIMEPROTOBUF))
assert.Equal(t, ProtoBuf, Default(http.MethodPost, MIMEPROTOBUF))
assert.Equal(t, ProtoBuf, Default(http.MethodPut, MIMEPROTOBUF))
assert.Equal(t, YAML, Default("POST", MIMEYAML))
assert.Equal(t, YAML, Default("PUT", MIMEYAML))
assert.Equal(t, YAML, Default("POST", MIMEYAML2))
assert.Equal(t, YAML, Default("PUT", MIMEYAML2))
assert.Equal(t, YAML, Default(http.MethodPost, MIMEYAML))
assert.Equal(t, YAML, Default(http.MethodPut, MIMEYAML))
assert.Equal(t, YAML, Default(http.MethodPost, MIMEYAML2))
assert.Equal(t, YAML, Default(http.MethodPut, MIMEYAML2))
assert.Equal(t, TOML, Default("POST", MIMETOML))
assert.Equal(t, TOML, Default("PUT", MIMETOML))
assert.Equal(t, TOML, Default(http.MethodPost, MIMETOML))
assert.Equal(t, TOML, Default(http.MethodPut, MIMETOML))
}
func TestBindingJSONNilBody(t *testing.T) {
@ -227,137 +227,137 @@ func TestBindingJSONStringMap(t *testing.T) {
}
func TestBindingForm(t *testing.T) {
testFormBinding(t, "POST",
testFormBinding(t, http.MethodPost,
"/", "/",
"foo=bar&bar=foo", "bar2=foo")
}
func TestBindingForm2(t *testing.T) {
testFormBinding(t, "GET",
testFormBinding(t, http.MethodGet,
"/?foo=bar&bar=foo", "/?bar2=foo",
"", "")
}
func TestBindingFormEmbeddedStruct(t *testing.T) {
testFormBindingEmbeddedStruct(t, "POST",
testFormBindingEmbeddedStruct(t, http.MethodPost,
"/", "/",
"page=1&size=2&appkey=test-appkey", "bar2=foo")
}
func TestBindingFormEmbeddedStruct2(t *testing.T) {
testFormBindingEmbeddedStruct(t, "GET",
testFormBindingEmbeddedStruct(t, http.MethodGet,
"/?page=1&size=2&appkey=test-appkey", "/?bar2=foo",
"", "")
}
func TestBindingFormDefaultValue(t *testing.T) {
testFormBindingDefaultValue(t, "POST",
testFormBindingDefaultValue(t, http.MethodPost,
"/", "/",
"foo=bar", "bar2=foo")
}
func TestBindingFormDefaultValue2(t *testing.T) {
testFormBindingDefaultValue(t, "GET",
testFormBindingDefaultValue(t, http.MethodGet,
"/?foo=bar", "/?bar2=foo",
"", "")
}
func TestBindingFormForTime(t *testing.T) {
testFormBindingForTime(t, "POST",
testFormBindingForTime(t, http.MethodPost,
"/", "/",
"time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033", "bar2=foo")
testFormBindingForTimeNotUnixFormat(t, "POST",
testFormBindingForTimeNotUnixFormat(t, http.MethodPost,
"/", "/",
"time_foo=2017-11-15&createTime=bad&unixTime=bad", "bar2=foo")
testFormBindingForTimeNotFormat(t, "POST",
testFormBindingForTimeNotFormat(t, http.MethodPost,
"/", "/",
"time_foo=2017-11-15", "bar2=foo")
testFormBindingForTimeFailFormat(t, "POST",
testFormBindingForTimeFailFormat(t, http.MethodPost,
"/", "/",
"time_foo=2017-11-15", "bar2=foo")
testFormBindingForTimeFailLocation(t, "POST",
testFormBindingForTimeFailLocation(t, http.MethodPost,
"/", "/",
"time_foo=2017-11-15", "bar2=foo")
}
func TestBindingFormForTime2(t *testing.T) {
testFormBindingForTime(t, "GET",
testFormBindingForTime(t, http.MethodGet,
"/?time_foo=2017-11-15&time_bar=&createTime=1562400033000000123&unixTime=1562400033", "/?bar2=foo",
"", "")
testFormBindingForTimeNotUnixFormat(t, "POST",
testFormBindingForTimeNotUnixFormat(t, http.MethodPost,
"/", "/",
"time_foo=2017-11-15&createTime=bad&unixTime=bad", "bar2=foo")
testFormBindingForTimeNotFormat(t, "GET",
testFormBindingForTimeNotFormat(t, http.MethodGet,
"/?time_foo=2017-11-15", "/?bar2=foo",
"", "")
testFormBindingForTimeFailFormat(t, "GET",
testFormBindingForTimeFailFormat(t, http.MethodGet,
"/?time_foo=2017-11-15", "/?bar2=foo",
"", "")
testFormBindingForTimeFailLocation(t, "GET",
testFormBindingForTimeFailLocation(t, http.MethodGet,
"/?time_foo=2017-11-15", "/?bar2=foo",
"", "")
}
func TestFormBindingIgnoreField(t *testing.T) {
testFormBindingIgnoreField(t, "POST",
testFormBindingIgnoreField(t, http.MethodPost,
"/", "/",
"-=bar", "")
}
func TestBindingFormInvalidName(t *testing.T) {
testFormBindingInvalidName(t, "POST",
testFormBindingInvalidName(t, http.MethodPost,
"/", "/",
"test_name=bar", "bar2=foo")
}
func TestBindingFormInvalidName2(t *testing.T) {
testFormBindingInvalidName2(t, "POST",
testFormBindingInvalidName2(t, http.MethodPost,
"/", "/",
"map_foo=bar", "bar2=foo")
}
func TestBindingFormForType(t *testing.T) {
testFormBindingForType(t, "POST",
testFormBindingForType(t, http.MethodPost,
"/", "/",
"map_foo={\"bar\":123}", "map_foo=1", "Map")
testFormBindingForType(t, "POST",
testFormBindingForType(t, http.MethodPost,
"/", "/",
"slice_foo=1&slice_foo=2", "bar2=1&bar2=2", "Slice")
testFormBindingForType(t, "GET",
testFormBindingForType(t, http.MethodGet,
"/?slice_foo=1&slice_foo=2", "/?bar2=1&bar2=2",
"", "", "Slice")
testFormBindingForType(t, "POST",
testFormBindingForType(t, http.MethodPost,
"/", "/",
"slice_map_foo=1&slice_map_foo=2", "bar2=1&bar2=2", "SliceMap")
testFormBindingForType(t, "GET",
testFormBindingForType(t, http.MethodGet,
"/?slice_map_foo=1&slice_map_foo=2", "/?bar2=1&bar2=2",
"", "", "SliceMap")
testFormBindingForType(t, "POST",
testFormBindingForType(t, http.MethodPost,
"/", "/",
"ptr_bar=test", "bar2=test", "Ptr")
testFormBindingForType(t, "GET",
testFormBindingForType(t, http.MethodGet,
"/?ptr_bar=test", "/?bar2=test",
"", "", "Ptr")
testFormBindingForType(t, "POST",
testFormBindingForType(t, http.MethodPost,
"/", "/",
"idx=123", "id1=1", "Struct")
testFormBindingForType(t, "GET",
testFormBindingForType(t, http.MethodGet,
"/?idx=123", "/?id1=1",
"", "", "Struct")
testFormBindingForType(t, "POST",
testFormBindingForType(t, http.MethodPost,
"/", "/",
"name=thinkerou", "name1=ou", "StructPointer")
testFormBindingForType(t, "GET",
testFormBindingForType(t, http.MethodGet,
"/?name=thinkerou", "/?name1=ou",
"", "", "StructPointer")
}
@ -374,7 +374,7 @@ func TestBindingFormStringMap(t *testing.T) {
func TestBindingFormStringSliceMap(t *testing.T) {
obj := make(map[string][]string)
req := requestWithBody("POST", "/", "foo=something&foo=bar&hello=world")
req := requestWithBody(http.MethodPost, "/", "foo=something&foo=bar&hello=world")
req.Header.Add("Content-Type", MIMEPOSTForm)
err := Form.Bind(req, &obj)
require.NoError(t, err)
@ -387,38 +387,38 @@ func TestBindingFormStringSliceMap(t *testing.T) {
assert.True(t, reflect.DeepEqual(obj, target))
objInvalid := make(map[string][]int)
req = requestWithBody("POST", "/", "foo=something&foo=bar&hello=world")
req = requestWithBody(http.MethodPost, "/", "foo=something&foo=bar&hello=world")
req.Header.Add("Content-Type", MIMEPOSTForm)
err = Form.Bind(req, &objInvalid)
require.Error(t, err)
}
func TestBindingQuery(t *testing.T) {
testQueryBinding(t, "POST",
testQueryBinding(t, http.MethodPost,
"/?foo=bar&bar=foo", "/",
"foo=unused", "bar2=foo")
}
func TestBindingQuery2(t *testing.T) {
testQueryBinding(t, "GET",
testQueryBinding(t, http.MethodGet,
"/?foo=bar&bar=foo", "/?bar2=foo",
"foo=unused", "")
}
func TestBindingQueryFail(t *testing.T) {
testQueryBindingFail(t, "POST",
testQueryBindingFail(t, http.MethodPost,
"/?map_foo=", "/",
"map_foo=unused", "bar2=foo")
}
func TestBindingQueryFail2(t *testing.T) {
testQueryBindingFail(t, "GET",
testQueryBindingFail(t, http.MethodGet,
"/?map_foo=", "/?bar2=foo",
"map_foo=unused", "")
}
func TestBindingQueryBoolFail(t *testing.T) {
testQueryBindingBoolFail(t, "GET",
testQueryBindingBoolFail(t, http.MethodGet,
"/?bool_foo=fasl", "/?bar2=foo",
"bool_foo=unused", "")
}
@ -427,7 +427,7 @@ func TestBindingQueryStringMap(t *testing.T) {
b := Query
obj := make(map[string]string)
req := requestWithBody("GET", "/?foo=bar&hello=world", "")
req := requestWithBody(http.MethodGet, "/?foo=bar&hello=world", "")
err := b.Bind(req, &obj)
require.NoError(t, err)
assert.NotNil(t, obj)
@ -436,7 +436,7 @@ func TestBindingQueryStringMap(t *testing.T) {
assert.Equal(t, "world", obj["hello"])
obj = make(map[string]string)
req = requestWithBody("GET", "/?foo=bar&foo=2&hello=world", "") // should pick last
req = requestWithBody(http.MethodGet, "/?foo=bar&foo=2&hello=world", "") // should pick last
err = b.Bind(req, &obj)
require.NoError(t, err)
assert.NotNil(t, obj)
@ -495,28 +495,28 @@ func TestBindingYAMLFail(t *testing.T) {
}
func createFormPostRequest(t *testing.T) *http.Request {
req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar&bar=foo"))
req, err := http.NewRequest(http.MethodPost, "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar&bar=foo"))
require.NoError(t, err)
req.Header.Set("Content-Type", MIMEPOSTForm)
return req
}
func createDefaultFormPostRequest(t *testing.T) *http.Request {
req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar"))
req, err := http.NewRequest(http.MethodPost, "/?foo=getfoo&bar=getbar", bytes.NewBufferString("foo=bar"))
require.NoError(t, err)
req.Header.Set("Content-Type", MIMEPOSTForm)
return req
}
func createFormPostRequestForMap(t *testing.T) *http.Request {
req, err := http.NewRequest("POST", "/?map_foo=getfoo", bytes.NewBufferString("map_foo={\"bar\":123}"))
req, err := http.NewRequest(http.MethodPost, "/?map_foo=getfoo", bytes.NewBufferString("map_foo={\"bar\":123}"))
require.NoError(t, err)
req.Header.Set("Content-Type", MIMEPOSTForm)
return req
}
func createFormPostRequestForMapFail(t *testing.T) *http.Request {
req, err := http.NewRequest("POST", "/?map_foo=getfoo", bytes.NewBufferString("map_foo=hello"))
req, err := http.NewRequest(http.MethodPost, "/?map_foo=getfoo", bytes.NewBufferString("map_foo=hello"))
require.NoError(t, err)
req.Header.Set("Content-Type", MIMEPOSTForm)
return req
@ -540,7 +540,7 @@ func createFormFilesMultipartRequest(t *testing.T) *http.Request {
_, err = io.Copy(fw, f)
require.NoError(t, err)
req, err2 := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
req, err2 := http.NewRequest(http.MethodPost, "/?foo=getfoo&bar=getbar", body)
require.NoError(t, err2)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
@ -565,7 +565,7 @@ func createFormFilesMultipartRequestFail(t *testing.T) *http.Request {
_, err = io.Copy(fw, f)
require.NoError(t, err)
req, err2 := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
req, err2 := http.NewRequest(http.MethodPost, "/?foo=getfoo&bar=getbar", body)
require.NoError(t, err2)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
@ -581,7 +581,7 @@ func createFormMultipartRequest(t *testing.T) *http.Request {
require.NoError(t, mw.SetBoundary(boundary))
require.NoError(t, mw.WriteField("foo", "bar"))
require.NoError(t, mw.WriteField("bar", "foo"))
req, err := http.NewRequest("POST", "/?foo=getfoo&bar=getbar", body)
req, err := http.NewRequest(http.MethodPost, "/?foo=getfoo&bar=getbar", body)
require.NoError(t, err)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
return req
@ -595,7 +595,7 @@ func createFormMultipartRequestForMap(t *testing.T) *http.Request {
require.NoError(t, mw.SetBoundary(boundary))
require.NoError(t, mw.WriteField("map_foo", "{\"bar\":123, \"name\":\"thinkerou\", \"pai\": 3.14}"))
req, err := http.NewRequest("POST", "/?map_foo=getfoo", body)
req, err := http.NewRequest(http.MethodPost, "/?map_foo=getfoo", body)
require.NoError(t, err)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
return req
@ -609,7 +609,7 @@ func createFormMultipartRequestForMapFail(t *testing.T) *http.Request {
require.NoError(t, mw.SetBoundary(boundary))
require.NoError(t, mw.WriteField("map_foo", "3.14"))
req, err := http.NewRequest("POST", "/?map_foo=getfoo", body)
req, err := http.NewRequest(http.MethodPost, "/?map_foo=getfoo", body)
require.NoError(t, err)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
return req
@ -731,7 +731,7 @@ func TestBindingProtoBufFail(t *testing.T) {
func TestValidationFails(t *testing.T) {
var obj FooStruct
req := requestWithBody("POST", "/", `{"bar": "foo"}`)
req := requestWithBody(http.MethodPost, "/", `{"bar": "foo"}`)
err := JSON.Bind(req, &obj)
require.Error(t, err)
}
@ -742,7 +742,7 @@ func TestValidationDisabled(t *testing.T) {
defer func() { Validator = backup }()
var obj FooStruct
req := requestWithBody("POST", "/", `{"bar": "foo"}`)
req := requestWithBody(http.MethodPost, "/", `{"bar": "foo"}`)
err := JSON.Bind(req, &obj)
require.NoError(t, err)
}
@ -753,7 +753,7 @@ func TestRequiredSucceeds(t *testing.T) {
}
var obj HogeStruct
req := requestWithBody("POST", "/", `{"hoge": 0}`)
req := requestWithBody(http.MethodPost, "/", `{"hoge": 0}`)
err := JSON.Bind(req, &obj)
require.NoError(t, err)
}
@ -764,7 +764,7 @@ func TestRequiredFails(t *testing.T) {
}
var obj HogeStruct
req := requestWithBody("POST", "/", `{"boen": 0}`)
req := requestWithBody(http.MethodPost, "/", `{"boen": 0}`)
err := JSON.Bind(req, &obj)
require.Error(t, err)
}
@ -778,12 +778,12 @@ func TestHeaderBinding(t *testing.T) {
}
var theader tHeader
req := requestWithBody("GET", "/", "")
req := requestWithBody(http.MethodGet, "/", "")
req.Header.Add("limit", "1000")
require.NoError(t, h.Bind(req, &theader))
assert.Equal(t, 1000, theader.Limit)
req = requestWithBody("GET", "/", "")
req = requestWithBody(http.MethodGet, "/", "")
req.Header.Add("fail", `{fail:fail}`)
type failStruct struct {
@ -843,7 +843,7 @@ func testFormBindingEmbeddedStruct(t *testing.T, method, path, badPath, body, ba
obj := QueryTest{}
req := requestWithBody(method, path, body)
if method == "POST" {
if method == http.MethodPost {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
err := b.Bind(req, &obj)
@ -859,7 +859,7 @@ func testFormBinding(t *testing.T, method, path, badPath, body, badBody string)
obj := FooBarStruct{}
req := requestWithBody(method, path, body)
if method == "POST" {
if method == http.MethodPost {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
err := b.Bind(req, &obj)
@ -879,7 +879,7 @@ func testFormBindingDefaultValue(t *testing.T, method, path, badPath, body, badB
obj := FooDefaultBarStruct{}
req := requestWithBody(method, path, body)
if method == "POST" {
if method == http.MethodPost {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
err := b.Bind(req, &obj)
@ -898,14 +898,14 @@ func TestFormBindingFail(t *testing.T) {
assert.Equal(t, "form", b.Name())
obj := FooBarStruct{}
req, _ := http.NewRequest("POST", "/", nil)
req, _ := http.NewRequest(http.MethodPost, "/", nil)
err := b.Bind(req, &obj)
require.Error(t, err)
}
func TestFormBindingMultipartFail(t *testing.T) {
obj := FooBarStruct{}
req, err := http.NewRequest("POST", "/", strings.NewReader("foo=bar"))
req, err := http.NewRequest(http.MethodPost, "/", strings.NewReader("foo=bar"))
require.NoError(t, err)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+";boundary=testboundary")
_, err = req.MultipartReader()
@ -919,7 +919,7 @@ func TestFormPostBindingFail(t *testing.T) {
assert.Equal(t, "form-urlencoded", b.Name())
obj := FooBarStruct{}
req, _ := http.NewRequest("POST", "/", nil)
req, _ := http.NewRequest(http.MethodPost, "/", nil)
err := b.Bind(req, &obj)
require.Error(t, err)
}
@ -929,7 +929,7 @@ func TestFormMultipartBindingFail(t *testing.T) {
assert.Equal(t, "multipart/form-data", b.Name())
obj := FooBarStruct{}
req, _ := http.NewRequest("POST", "/", nil)
req, _ := http.NewRequest(http.MethodPost, "/", nil)
err := b.Bind(req, &obj)
require.Error(t, err)
}
@ -940,7 +940,7 @@ func testFormBindingForTime(t *testing.T, method, path, badPath, body, badBody s
obj := FooBarStructForTimeType{}
req := requestWithBody(method, path, body)
if method == "POST" {
if method == http.MethodPost {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
err := b.Bind(req, &obj)
@ -965,7 +965,7 @@ func testFormBindingForTimeNotUnixFormat(t *testing.T, method, path, badPath, bo
obj := FooStructForTimeTypeNotUnixFormat{}
req := requestWithBody(method, path, body)
if method == "POST" {
if method == http.MethodPost {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
err := b.Bind(req, &obj)
@ -983,7 +983,7 @@ func testFormBindingForTimeNotFormat(t *testing.T, method, path, badPath, body,
obj := FooStructForTimeTypeNotFormat{}
req := requestWithBody(method, path, body)
if method == "POST" {
if method == http.MethodPost {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
err := b.Bind(req, &obj)
@ -1001,7 +1001,7 @@ func testFormBindingForTimeFailFormat(t *testing.T, method, path, badPath, body,
obj := FooStructForTimeTypeFailFormat{}
req := requestWithBody(method, path, body)
if method == "POST" {
if method == http.MethodPost {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
err := b.Bind(req, &obj)
@ -1019,7 +1019,7 @@ func testFormBindingForTimeFailLocation(t *testing.T, method, path, badPath, bod
obj := FooStructForTimeTypeFailLocation{}
req := requestWithBody(method, path, body)
if method == "POST" {
if method == http.MethodPost {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
err := b.Bind(req, &obj)
@ -1037,7 +1037,7 @@ func testFormBindingIgnoreField(t *testing.T, method, path, badPath, body, badBo
obj := FooStructForIgnoreFormTag{}
req := requestWithBody(method, path, body)
if method == "POST" {
if method == http.MethodPost {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
err := b.Bind(req, &obj)
@ -1052,7 +1052,7 @@ func testFormBindingInvalidName(t *testing.T, method, path, badPath, body, badBo
obj := InvalidNameType{}
req := requestWithBody(method, path, body)
if method == "POST" {
if method == http.MethodPost {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
err := b.Bind(req, &obj)
@ -1071,7 +1071,7 @@ func testFormBindingInvalidName2(t *testing.T, method, path, badPath, body, badB
obj := InvalidNameMapType{}
req := requestWithBody(method, path, body)
if method == "POST" {
if method == http.MethodPost {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
err := b.Bind(req, &obj)
@ -1088,7 +1088,7 @@ func testFormBindingForType(t *testing.T, method, path, badPath, body, badBody s
assert.Equal(t, "form", b.Name())
req := requestWithBody(method, path, body)
if method == "POST" {
if method == http.MethodPost {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
switch typ {
@ -1159,7 +1159,7 @@ func testQueryBinding(t *testing.T, method, path, badPath, body, badBody string)
obj := FooBarStruct{}
req := requestWithBody(method, path, body)
if method == "POST" {
if method == http.MethodPost {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
err := b.Bind(req, &obj)
@ -1174,7 +1174,7 @@ func testQueryBindingFail(t *testing.T, method, path, badPath, body, badBody str
obj := FooStructForMapType{}
req := requestWithBody(method, path, body)
if method == "POST" {
if method == http.MethodPost {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
err := b.Bind(req, &obj)
@ -1187,7 +1187,7 @@ func testQueryBindingBoolFail(t *testing.T, method, path, badPath, body, badBody
obj := FooStructForBoolType{}
req := requestWithBody(method, path, body)
if method == "POST" {
if method == http.MethodPost {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
err := b.Bind(req, &obj)
@ -1198,13 +1198,13 @@ func testBodyBinding(t *testing.T, b Binding, name, path, badPath, body, badBody
assert.Equal(t, name, b.Name())
obj := FooStruct{}
req := requestWithBody("POST", path, body)
req := requestWithBody(http.MethodPost, path, body)
err := b.Bind(req, &obj)
require.NoError(t, err)
assert.Equal(t, "bar", obj.Foo)
obj = FooStruct{}
req = requestWithBody("POST", badPath, badBody)
req = requestWithBody(http.MethodPost, badPath, badBody)
err = JSON.Bind(req, &obj)
require.Error(t, err)
}
@ -1213,19 +1213,19 @@ func testBodyBindingSlice(t *testing.T, b Binding, name, path, badPath, body, ba
assert.Equal(t, name, b.Name())
var obj1 []FooStruct
req := requestWithBody("POST", path, body)
req := requestWithBody(http.MethodPost, path, body)
err := b.Bind(req, &obj1)
require.NoError(t, err)
var obj2 []FooStruct
req = requestWithBody("POST", badPath, badBody)
req = requestWithBody(http.MethodPost, badPath, badBody)
err = JSON.Bind(req, &obj2)
require.Error(t, err)
}
func testBodyBindingStringMap(t *testing.T, b Binding, path, badPath, body, badBody string) {
obj := make(map[string]string)
req := requestWithBody("POST", path, body)
req := requestWithBody(http.MethodPost, path, body)
if b.Name() == "form" {
req.Header.Add("Content-Type", MIMEPOSTForm)
}
@ -1238,13 +1238,13 @@ func testBodyBindingStringMap(t *testing.T, b Binding, path, badPath, body, badB
if badPath != "" && badBody != "" {
obj = make(map[string]string)
req = requestWithBody("POST", badPath, badBody)
req = requestWithBody(http.MethodPost, badPath, badBody)
err = b.Bind(req, &obj)
require.Error(t, err)
}
objInt := make(map[string]int)
req = requestWithBody("POST", path, body)
req = requestWithBody(http.MethodPost, path, body)
err = b.Bind(req, &objInt)
require.Error(t, err)
}
@ -1253,7 +1253,7 @@ func testBodyBindingUseNumber(t *testing.T, b Binding, name, path, badPath, body
assert.Equal(t, name, b.Name())
obj := FooStructUseNumber{}
req := requestWithBody("POST", path, body)
req := requestWithBody(http.MethodPost, path, body)
EnableDecoderUseNumber = true
err := b.Bind(req, &obj)
require.NoError(t, err)
@ -1263,7 +1263,7 @@ func testBodyBindingUseNumber(t *testing.T, b Binding, name, path, badPath, body
assert.Equal(t, int64(123), v)
obj = FooStructUseNumber{}
req = requestWithBody("POST", badPath, badBody)
req = requestWithBody(http.MethodPost, badPath, badBody)
err = JSON.Bind(req, &obj)
require.Error(t, err)
}
@ -1272,7 +1272,7 @@ func testBodyBindingUseNumber2(t *testing.T, b Binding, name, path, badPath, bod
assert.Equal(t, name, b.Name())
obj := FooStructUseNumber{}
req := requestWithBody("POST", path, body)
req := requestWithBody(http.MethodPost, path, body)
EnableDecoderUseNumber = false
err := b.Bind(req, &obj)
require.NoError(t, err)
@ -1281,7 +1281,7 @@ func testBodyBindingUseNumber2(t *testing.T, b Binding, name, path, badPath, bod
assert.InDelta(t, float64(123), obj.Foo, 0.01)
obj = FooStructUseNumber{}
req = requestWithBody("POST", badPath, badBody)
req = requestWithBody(http.MethodPost, badPath, badBody)
err = JSON.Bind(req, &obj)
require.Error(t, err)
}
@ -1293,13 +1293,13 @@ func testBodyBindingDisallowUnknownFields(t *testing.T, b Binding, path, badPath
}()
obj := FooStructDisallowUnknownFields{}
req := requestWithBody("POST", path, body)
req := requestWithBody(http.MethodPost, path, body)
err := b.Bind(req, &obj)
require.NoError(t, err)
assert.Equal(t, "bar", obj.Foo)
obj = FooStructDisallowUnknownFields{}
req = requestWithBody("POST", badPath, badBody)
req = requestWithBody(http.MethodPost, badPath, badBody)
err = JSON.Bind(req, &obj)
require.Error(t, err)
assert.Contains(t, err.Error(), "what")
@ -1309,13 +1309,13 @@ func testBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body, bad
assert.Equal(t, name, b.Name())
obj := FooStruct{}
req := requestWithBody("POST", path, body)
req := requestWithBody(http.MethodPost, path, body)
err := b.Bind(req, &obj)
require.Error(t, err)
assert.Equal(t, "", obj.Foo)
obj = FooStruct{}
req = requestWithBody("POST", badPath, badBody)
req = requestWithBody(http.MethodPost, badPath, badBody)
err = JSON.Bind(req, &obj)
require.Error(t, err)
}
@ -1324,14 +1324,14 @@ func testProtoBodyBinding(t *testing.T, b Binding, name, path, badPath, body, ba
assert.Equal(t, name, b.Name())
obj := protoexample.Test{}
req := requestWithBody("POST", path, body)
req := requestWithBody(http.MethodPost, path, body)
req.Header.Add("Content-Type", MIMEPROTOBUF)
err := b.Bind(req, &obj)
require.NoError(t, err)
assert.Equal(t, "yes", *obj.Label)
obj = protoexample.Test{}
req = requestWithBody("POST", badPath, badBody)
req = requestWithBody(http.MethodPost, badPath, badBody)
req.Header.Add("Content-Type", MIMEPROTOBUF)
err = ProtoBuf.Bind(req, &obj)
require.Error(t, err)
@ -1358,28 +1358,28 @@ func TestPlainBinding(t *testing.T) {
assert.Equal(t, "plain", p.Name())
var s string
req := requestWithBody("POST", "/", "test string")
req := requestWithBody(http.MethodPost, "/", "test string")
require.NoError(t, p.Bind(req, &s))
assert.Equal(t, "test string", s)
var bs []byte
req = requestWithBody("POST", "/", "test []byte")
req = requestWithBody(http.MethodPost, "/", "test []byte")
require.NoError(t, p.Bind(req, &bs))
assert.Equal(t, bs, []byte("test []byte"))
var i int
req = requestWithBody("POST", "/", "test fail")
req = requestWithBody(http.MethodPost, "/", "test fail")
require.Error(t, p.Bind(req, &i))
req = requestWithBody("POST", "/", "")
req = requestWithBody(http.MethodPost, "/", "")
req.Body = &failRead{}
require.Error(t, p.Bind(req, &s))
req = requestWithBody("POST", "/", "")
req = requestWithBody(http.MethodPost, "/", "")
require.NoError(t, p.Bind(req, nil))
var ptr *string
req = requestWithBody("POST", "/", "")
req = requestWithBody(http.MethodPost, "/", "")
require.NoError(t, p.Bind(req, ptr))
}
@ -1387,7 +1387,7 @@ func testProtoBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body
assert.Equal(t, name, b.Name())
obj := protoexample.Test{}
req := requestWithBody("POST", path, body)
req := requestWithBody(http.MethodPost, path, body)
req.Body = io.NopCloser(&hook{})
req.Header.Add("Content-Type", MIMEPROTOBUF)
@ -1402,7 +1402,7 @@ func testProtoBodyBindingFail(t *testing.T, b Binding, name, path, badPath, body
assert.Equal(t, "obj is not ProtoMessage", err.Error())
obj = protoexample.Test{}
req = requestWithBody("POST", badPath, badBody)
req = requestWithBody(http.MethodPost, badPath, badBody)
req.Header.Add("Content-Type", MIMEPROTOBUF)
err = ProtoBuf.Bind(req, &obj)
require.Error(t, err)

View File

@ -6,7 +6,7 @@ package binding
import (
"encoding/hex"
"fmt"
"errors"
"mime/multipart"
"reflect"
"strconv"
@ -494,7 +494,7 @@ type customUnmarshalParamType struct {
func (f *customUnmarshalParamType) UnmarshalParam(param string) error {
parts := strings.Split(param, ":")
if len(parts) != 3 {
return fmt.Errorf("invalid format")
return errors.New("invalid format")
}
f.Protocol = parts[0]
f.Path = parts[1]
@ -556,7 +556,7 @@ func (p *customPath) UnmarshalParam(param string) error {
elems := strings.Split(param, "/")
n := len(elems)
if n < 2 {
return fmt.Errorf("invalid format")
return errors.New("invalid format")
}
*p = elems
@ -600,7 +600,7 @@ func (o *objectID) UnmarshalParam(param string) error {
func convertTo(s string) (objectID, error) {
var nilObjectID objectID
if len(s) != 24 {
return nilObjectID, fmt.Errorf("invalid format")
return nilObjectID, errors.New("invalid format")
}
var oid [12]byte

View File

@ -116,7 +116,7 @@ func createRequestMultipartFiles(t *testing.T, files ...testFile) *http.Request
err := mw.Close()
require.NoError(t, err)
req, err := http.NewRequest("POST", "/", &body)
req, err := http.NewRequest(http.MethodPost, "/", &body)
require.NoError(t, err)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+mw.Boundary())

View File

@ -7,6 +7,7 @@ package gin
import (
"errors"
"io"
"io/fs"
"log"
"math"
"mime/multipart"
@ -186,10 +187,9 @@ func (c *Context) FullPath() string {
func (c *Context) Next() {
c.index++
for c.index < int8(len(c.handlers)) {
if c.handlers[c.index] == nil {
continue
if c.handlers[c.index] != nil {
c.handlers[c.index](c)
}
c.handlers[c.index](c)
c.index++
}
}
@ -291,248 +291,171 @@ func (c *Context) MustGet(key string) any {
panic("Key \"" + key + "\" does not exist")
}
// GetString returns the value associated with the key as a string.
func (c *Context) GetString(key string) (s string) {
func getTyped[T any](c *Context, key string) (res T) {
if val, ok := c.Get(key); ok && val != nil {
s, _ = val.(string)
res, _ = val.(T)
}
return
}
// GetString returns the value associated with the key as a string.
func (c *Context) GetString(key string) (s string) {
return getTyped[string](c, key)
}
// GetBool returns the value associated with the key as a boolean.
func (c *Context) GetBool(key string) (b bool) {
if val, ok := c.Get(key); ok && val != nil {
b, _ = val.(bool)
}
return
return getTyped[bool](c, key)
}
// GetInt returns the value associated with the key as an integer.
func (c *Context) GetInt(key string) (i int) {
if val, ok := c.Get(key); ok && val != nil {
i, _ = val.(int)
}
return
return getTyped[int](c, key)
}
// GetInt8 returns the value associated with the key as an integer 8.
func (c *Context) GetInt8(key string) (i8 int8) {
if val, ok := c.Get(key); ok && val != nil {
i8, _ = val.(int8)
}
return
return getTyped[int8](c, key)
}
// GetInt16 returns the value associated with the key as an integer 16.
func (c *Context) GetInt16(key string) (i16 int16) {
if val, ok := c.Get(key); ok && val != nil {
i16, _ = val.(int16)
}
return
return getTyped[int16](c, key)
}
// GetInt32 returns the value associated with the key as an integer 32.
func (c *Context) GetInt32(key string) (i32 int32) {
if val, ok := c.Get(key); ok && val != nil {
i32, _ = val.(int32)
}
return
return getTyped[int32](c, key)
}
// GetInt64 returns the value associated with the key as an integer 64.
func (c *Context) GetInt64(key string) (i64 int64) {
if val, ok := c.Get(key); ok && val != nil {
i64, _ = val.(int64)
}
return
return getTyped[int64](c, key)
}
// GetUint returns the value associated with the key as an unsigned integer.
func (c *Context) GetUint(key string) (ui uint) {
if val, ok := c.Get(key); ok && val != nil {
ui, _ = val.(uint)
}
return
return getTyped[uint](c, key)
}
// GetUint8 returns the value associated with the key as an unsigned integer 8.
func (c *Context) GetUint8(key string) (ui8 uint8) {
if val, ok := c.Get(key); ok && val != nil {
ui8, _ = val.(uint8)
}
return
return getTyped[uint8](c, key)
}
// GetUint16 returns the value associated with the key as an unsigned integer 16.
func (c *Context) GetUint16(key string) (ui16 uint16) {
if val, ok := c.Get(key); ok && val != nil {
ui16, _ = val.(uint16)
}
return
return getTyped[uint16](c, key)
}
// GetUint32 returns the value associated with the key as an unsigned integer 32.
func (c *Context) GetUint32(key string) (ui32 uint32) {
if val, ok := c.Get(key); ok && val != nil {
ui32, _ = val.(uint32)
}
return
return getTyped[uint32](c, key)
}
// GetUint64 returns the value associated with the key as an unsigned integer 64.
func (c *Context) GetUint64(key string) (ui64 uint64) {
if val, ok := c.Get(key); ok && val != nil {
ui64, _ = val.(uint64)
}
return
return getTyped[uint64](c, key)
}
// GetFloat32 returns the value associated with the key as a float32.
func (c *Context) GetFloat32(key string) (f32 float32) {
if val, ok := c.Get(key); ok && val != nil {
f32, _ = val.(float32)
}
return
return getTyped[float32](c, key)
}
// GetFloat64 returns the value associated with the key as a float64.
func (c *Context) GetFloat64(key string) (f64 float64) {
if val, ok := c.Get(key); ok && val != nil {
f64, _ = val.(float64)
}
return
return getTyped[float64](c, key)
}
// GetTime returns the value associated with the key as time.
func (c *Context) GetTime(key string) (t time.Time) {
if val, ok := c.Get(key); ok && val != nil {
t, _ = val.(time.Time)
}
return
return getTyped[time.Time](c, key)
}
// GetDuration returns the value associated with the key as a duration.
func (c *Context) GetDuration(key string) (d time.Duration) {
if val, ok := c.Get(key); ok && val != nil {
d, _ = val.(time.Duration)
}
return
return getTyped[time.Duration](c, key)
}
// GetIntSlice returns the value associated with the key as a slice of integers.
func (c *Context) GetIntSlice(key string) (is []int) {
if val, ok := c.Get(key); ok && val != nil {
is, _ = val.([]int)
}
return
return getTyped[[]int](c, key)
}
// GetInt8Slice returns the value associated with the key as a slice of int8 integers.
func (c *Context) GetInt8Slice(key string) (i8s []int8) {
if val, ok := c.Get(key); ok && val != nil {
i8s, _ = val.([]int8)
}
return
return getTyped[[]int8](c, key)
}
// GetInt16Slice returns the value associated with the key as a slice of int16 integers.
func (c *Context) GetInt16Slice(key string) (i16s []int16) {
if val, ok := c.Get(key); ok && val != nil {
i16s, _ = val.([]int16)
}
return
return getTyped[[]int16](c, key)
}
// GetInt32Slice returns the value associated with the key as a slice of int32 integers.
func (c *Context) GetInt32Slice(key string) (i32s []int32) {
if val, ok := c.Get(key); ok && val != nil {
i32s, _ = val.([]int32)
}
return
return getTyped[[]int32](c, key)
}
// GetInt64Slice returns the value associated with the key as a slice of int64 integers.
func (c *Context) GetInt64Slice(key string) (i64s []int64) {
if val, ok := c.Get(key); ok && val != nil {
i64s, _ = val.([]int64)
}
return
return getTyped[[]int64](c, key)
}
// GetUintSlice returns the value associated with the key as a slice of unsigned integers.
func (c *Context) GetUintSlice(key string) (uis []uint) {
if val, ok := c.Get(key); ok && val != nil {
uis, _ = val.([]uint)
}
return
return getTyped[[]uint](c, key)
}
// GetUint8Slice returns the value associated with the key as a slice of uint8 integers.
func (c *Context) GetUint8Slice(key string) (ui8s []uint8) {
if val, ok := c.Get(key); ok && val != nil {
ui8s, _ = val.([]uint8)
}
return
return getTyped[[]uint8](c, key)
}
// GetUint16Slice returns the value associated with the key as a slice of uint16 integers.
func (c *Context) GetUint16Slice(key string) (ui16s []uint16) {
if val, ok := c.Get(key); ok && val != nil {
ui16s, _ = val.([]uint16)
}
return
return getTyped[[]uint16](c, key)
}
// GetUint32Slice returns the value associated with the key as a slice of uint32 integers.
func (c *Context) GetUint32Slice(key string) (ui32s []uint32) {
if val, ok := c.Get(key); ok && val != nil {
ui32s, _ = val.([]uint32)
}
return
return getTyped[[]uint32](c, key)
}
// GetUint64Slice returns the value associated with the key as a slice of uint64 integers.
func (c *Context) GetUint64Slice(key string) (ui64s []uint64) {
if val, ok := c.Get(key); ok && val != nil {
ui64s, _ = val.([]uint64)
}
return
return getTyped[[]uint64](c, key)
}
// GetFloat32Slice returns the value associated with the key as a slice of float32 numbers.
func (c *Context) GetFloat32Slice(key string) (f32s []float32) {
if val, ok := c.Get(key); ok && val != nil {
f32s, _ = val.([]float32)
}
return
return getTyped[[]float32](c, key)
}
// GetFloat64Slice returns the value associated with the key as a slice of float64 numbers.
func (c *Context) GetFloat64Slice(key string) (f64s []float64) {
if val, ok := c.Get(key); ok && val != nil {
f64s, _ = val.([]float64)
}
return
return getTyped[[]float64](c, key)
}
// GetStringSlice returns the value associated with the key as a slice of strings.
func (c *Context) GetStringSlice(key string) (ss []string) {
if val, ok := c.Get(key); ok && val != nil {
ss, _ = val.([]string)
}
return
return getTyped[[]string](c, key)
}
// GetStringMap returns the value associated with the key as a map of interfaces.
func (c *Context) GetStringMap(key string) (sm map[string]any) {
if val, ok := c.Get(key); ok && val != nil {
sm, _ = val.(map[string]any)
}
return
return getTyped[map[string]any](c, key)
}
// GetStringMapString returns the value associated with the key as a map of strings.
func (c *Context) GetStringMapString(key string) (sms map[string]string) {
if val, ok := c.Get(key); ok && val != nil {
sms, _ = val.(map[string]string)
}
return
return getTyped[map[string]string](c, key)
}
// GetStringMapStringSlice returns the value associated with the key as a map to a slice of strings.
func (c *Context) GetStringMapStringSlice(key string) (smss map[string][]string) {
if val, ok := c.Get(key); ok && val != nil {
smss, _ = val.(map[string][]string)
}
return
return getTyped[map[string][]string](c, key)
}
/************************************/
@ -754,14 +677,22 @@ func (c *Context) MultipartForm() (*multipart.Form, error) {
}
// SaveUploadedFile uploads the form file to specific dst.
func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst string) error {
func (c *Context) SaveUploadedFile(file *multipart.FileHeader, dst string, perm ...fs.FileMode) error {
src, err := file.Open()
if err != nil {
return err
}
defer src.Close()
if err = os.MkdirAll(filepath.Dir(dst), 0o750); err != nil {
if len(perm) <= 0 {
perm = append(perm, 0o750)
}
if err = os.MkdirAll(filepath.Dir(dst), perm[0]); err != nil {
return err
}
if err = os.Chmod(filepath.Dir(dst), perm[0]); err != nil {
return err
}

View File

@ -11,13 +11,16 @@ import (
"fmt"
"html/template"
"io"
"io/fs"
"mime/multipart"
"net"
"net/http"
"net/http/httptest"
"net/url"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"sync"
"testing"
@ -59,7 +62,7 @@ func createMultipartRequest() *http.Request {
must(mw.WriteField("time_location", "31/12/2016 14:55"))
must(mw.WriteField("names[a]", "thinkerou"))
must(mw.WriteField("names[b]", "tianou"))
req, err := http.NewRequest("POST", "/", body)
req, err := http.NewRequest(http.MethodPost, "/", body)
must(err)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
return req
@ -80,7 +83,7 @@ func TestContextFormFile(t *testing.T) {
require.NoError(t, err)
mw.Close()
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", buf)
c.Request, _ = http.NewRequest(http.MethodPost, "/", buf)
c.Request.Header.Set("Content-Type", mw.FormDataContentType())
f, err := c.FormFile("file")
require.NoError(t, err)
@ -94,7 +97,7 @@ func TestContextFormFileFailed(t *testing.T) {
mw := multipart.NewWriter(buf)
mw.Close()
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "/", nil)
c.Request.Header.Set("Content-Type", mw.FormDataContentType())
c.engine.MaxMultipartMemory = 8 << 20
f, err := c.FormFile("file")
@ -112,7 +115,7 @@ func TestContextMultipartForm(t *testing.T) {
require.NoError(t, err)
mw.Close()
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", buf)
c.Request, _ = http.NewRequest(http.MethodPost, "/", buf)
c.Request.Header.Set("Content-Type", mw.FormDataContentType())
f, err := c.MultipartForm()
require.NoError(t, err)
@ -127,7 +130,7 @@ func TestSaveUploadedOpenFailed(t *testing.T) {
mw.Close()
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", buf)
c.Request, _ = http.NewRequest(http.MethodPost, "/", buf)
c.Request.Header.Set("Content-Type", mw.FormDataContentType())
f := &multipart.FileHeader{
@ -145,7 +148,7 @@ func TestSaveUploadedCreateFailed(t *testing.T) {
require.NoError(t, err)
mw.Close()
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", buf)
c.Request, _ = http.NewRequest(http.MethodPost, "/", buf)
c.Request.Header.Set("Content-Type", mw.FormDataContentType())
f, err := c.FormFile("file")
require.NoError(t, err)
@ -154,6 +157,45 @@ func TestSaveUploadedCreateFailed(t *testing.T) {
require.Error(t, c.SaveUploadedFile(f, "/"))
}
func TestSaveUploadedFileWithPermission(t *testing.T) {
buf := new(bytes.Buffer)
mw := multipart.NewWriter(buf)
w, err := mw.CreateFormFile("file", "permission_test")
require.NoError(t, err)
_, err = w.Write([]byte("permission_test"))
require.NoError(t, err)
mw.Close()
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", buf)
c.Request.Header.Set("Content-Type", mw.FormDataContentType())
f, err := c.FormFile("file")
require.NoError(t, err)
assert.Equal(t, "permission_test", f.Filename)
var mode fs.FileMode = 0o755
require.NoError(t, c.SaveUploadedFile(f, "permission_test", mode))
info, err := os.Stat(filepath.Dir("permission_test"))
require.NoError(t, err)
assert.Equal(t, info.Mode().Perm(), mode)
}
func TestSaveUploadedFileWithPermissionFailed(t *testing.T) {
buf := new(bytes.Buffer)
mw := multipart.NewWriter(buf)
w, err := mw.CreateFormFile("file", "permission_test")
require.NoError(t, err)
_, err = w.Write([]byte("permission_test"))
require.NoError(t, err)
mw.Close()
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", buf)
c.Request.Header.Set("Content-Type", mw.FormDataContentType())
f, err := c.FormFile("file")
require.NoError(t, err)
assert.Equal(t, "permission_test", f.Filename)
var mode fs.FileMode = 0o644
require.Error(t, c.SaveUploadedFile(f, "test/permission_test", mode))
}
func TestContextReset(t *testing.T) {
router := New()
c := router.allocateContext(0)
@ -480,7 +522,7 @@ func TestContextGetStringMapStringSlice(t *testing.T) {
func TestContextCopy(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.index = 2
c.Request, _ = http.NewRequest("POST", "/hola", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "/hola", nil)
c.handlers = HandlersChain{func(c *Context) {}}
c.Params = Params{Param{Key: "foo", Value: "bar"}}
c.Set("foo", "bar")
@ -537,7 +579,7 @@ func TestContextHandler(t *testing.T) {
func TestContextQuery(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("GET", "http://example.com/?foo=bar&page=10&id=", nil)
c.Request, _ = http.NewRequest(http.MethodGet, "http://example.com/?foo=bar&page=10&id=", nil)
value, ok := c.GetQuery("foo")
assert.True(t, ok)
@ -610,7 +652,6 @@ func TestContextInitQueryCache(t *testing.T) {
assert.Equal(t, test.expectedQueryCache, test.testContext.queryCache)
})
}
}
func TestContextDefaultQueryOnEmptyRequest(t *testing.T) {
@ -631,7 +672,7 @@ func TestContextDefaultQueryOnEmptyRequest(t *testing.T) {
func TestContextQueryAndPostForm(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
body := bytes.NewBufferString("foo=bar&page=11&both=&foo=second")
c.Request, _ = http.NewRequest("POST",
c.Request, _ = http.NewRequest(http.MethodPost,
"/?both=GET&id=main&id=omit&array[]=first&array[]=second&ids[a]=hi&ids[b]=3.14", body)
c.Request.Header.Add("Content-Type", MIMEPOSTForm)
@ -651,7 +692,7 @@ func TestContextQueryAndPostForm(t *testing.T) {
assert.Empty(t, value)
assert.Empty(t, c.PostForm("both"))
assert.Empty(t, c.DefaultPostForm("both", "nothing"))
assert.Equal(t, "GET", c.Query("both"), "GET")
assert.Equal(t, http.MethodGet, c.Query("both"), http.MethodGet)
value, ok = c.GetQuery("id")
assert.True(t, ok)
@ -699,7 +740,7 @@ func TestContextQueryAndPostForm(t *testing.T) {
values = c.QueryArray("both")
assert.Len(t, values, 1)
assert.Equal(t, "GET", values[0])
assert.Equal(t, http.MethodGet, values[0])
dicts, ok := c.GetQueryMap("ids")
assert.True(t, ok)
@ -834,7 +875,7 @@ func TestContextSetCookiePathEmpty(t *testing.T) {
func TestContextGetCookie(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("GET", "/get", nil)
c.Request, _ = http.NewRequest(http.MethodGet, "/get", nil)
c.Request.Header.Set("Cookie", "user=gin")
cookie, _ := c.Cookie("user")
assert.Equal(t, "gin", cookie)
@ -886,7 +927,7 @@ func TestContextRenderJSON(t *testing.T) {
func TestContextRenderJSONP(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "http://example.com/?callback=x", nil)
c.Request, _ = http.NewRequest(http.MethodGet, "http://example.com/?callback=x", nil)
c.JSONP(http.StatusCreated, H{"foo": "bar"})
@ -900,7 +941,7 @@ func TestContextRenderJSONP(t *testing.T) {
func TestContextRenderJSONPWithoutCallback(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "http://example.com", nil)
c.Request, _ = http.NewRequest(http.MethodGet, "http://example.com", nil)
c.JSONP(http.StatusCreated, H{"foo": "bar"})
@ -1043,7 +1084,7 @@ func TestContextRenderHTML2(t *testing.T) {
c, router := CreateTestContext(w)
// print debug warning log when Engine.trees > 0
router.addRoute("GET", "/", HandlersChain{func(_ *Context) {}})
router.addRoute(http.MethodGet, "/", HandlersChain{func(_ *Context) {}})
assert.Len(t, router.trees, 1)
templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
@ -1199,7 +1240,7 @@ func TestContextRenderFile(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "/", nil)
c.Request, _ = http.NewRequest(http.MethodGet, "/", nil)
c.File("./gin.go")
assert.Equal(t, http.StatusOK, w.Code)
@ -1213,7 +1254,7 @@ func TestContextRenderFileFromFS(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("GET", "/some/path", nil)
c.Request, _ = http.NewRequest(http.MethodGet, "/some/path", nil)
c.FileFromFS("./gin.go", Dir(".", false))
assert.Equal(t, http.StatusOK, w.Code)
@ -1229,7 +1270,7 @@ func TestContextRenderAttachment(t *testing.T) {
c, _ := CreateTestContext(w)
newFilename := "new_filename.go"
c.Request, _ = http.NewRequest("GET", "/", nil)
c.Request, _ = http.NewRequest(http.MethodGet, "/", nil)
c.FileAttachment("./gin.go", newFilename)
assert.Equal(t, 200, w.Code)
@ -1243,7 +1284,7 @@ func TestContextRenderAndEscapeAttachment(t *testing.T) {
maliciousFilename := "tampering_field.sh\"; \\\"; dummy=.go"
actualEscapedResponseFilename := "tampering_field.sh\\\"; \\\\\\\"; dummy=.go"
c.Request, _ = http.NewRequest("GET", "/", nil)
c.Request, _ = http.NewRequest(http.MethodGet, "/", nil)
c.FileAttachment("./gin.go", maliciousFilename)
assert.Equal(t, 200, w.Code)
@ -1256,7 +1297,7 @@ func TestContextRenderUTF8Attachment(t *testing.T) {
c, _ := CreateTestContext(w)
newFilename := "new🧡_filename.go"
c.Request, _ = http.NewRequest("GET", "/", nil)
c.Request, _ = http.NewRequest(http.MethodGet, "/", nil)
c.FileAttachment("./gin.go", newFilename)
assert.Equal(t, 200, w.Code)
@ -1335,7 +1376,7 @@ func TestContextRenderRedirectWithRelativePath(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "http://example.com", nil)
assert.Panics(t, func() { c.Redirect(299, "/new_path") })
assert.Panics(t, func() { c.Redirect(309, "/new_path") })
@ -1349,7 +1390,7 @@ func TestContextRenderRedirectWithAbsolutePath(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "http://example.com", nil)
c.Redirect(http.StatusFound, "http://google.com")
c.Writer.WriteHeaderNow()
@ -1361,7 +1402,7 @@ func TestContextRenderRedirectWith201(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "http://example.com", nil)
c.Redirect(http.StatusCreated, "/resource")
c.Writer.WriteHeaderNow()
@ -1371,7 +1412,7 @@ func TestContextRenderRedirectWith201(t *testing.T) {
func TestContextRenderRedirectAll(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "http://example.com", nil)
assert.Panics(t, func() { c.Redirect(http.StatusOK, "/resource") })
assert.Panics(t, func() { c.Redirect(http.StatusAccepted, "/resource") })
assert.Panics(t, func() { c.Redirect(299, "/resource") })
@ -1383,7 +1424,7 @@ func TestContextRenderRedirectAll(t *testing.T) {
func TestContextNegotiationWithJSON(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "", nil)
c.Negotiate(http.StatusOK, Negotiate{
Offered: []string{MIMEJSON, MIMEXML, MIMEYAML, MIMEYAML2},
@ -1398,7 +1439,7 @@ func TestContextNegotiationWithJSON(t *testing.T) {
func TestContextNegotiationWithXML(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "", nil)
c.Negotiate(http.StatusOK, Negotiate{
Offered: []string{MIMEXML, MIMEJSON, MIMEYAML, MIMEYAML2},
@ -1413,7 +1454,7 @@ func TestContextNegotiationWithXML(t *testing.T) {
func TestContextNegotiationWithYAML(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "", nil)
c.Negotiate(http.StatusOK, Negotiate{
Offered: []string{MIMEYAML, MIMEXML, MIMEJSON, MIMETOML, MIMEYAML2},
@ -1428,7 +1469,7 @@ func TestContextNegotiationWithYAML(t *testing.T) {
func TestContextNegotiationWithTOML(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "", nil)
c.Negotiate(http.StatusOK, Negotiate{
Offered: []string{MIMETOML, MIMEXML, MIMEJSON, MIMEYAML, MIMEYAML2},
@ -1443,7 +1484,7 @@ func TestContextNegotiationWithTOML(t *testing.T) {
func TestContextNegotiationWithHTML(t *testing.T) {
w := httptest.NewRecorder()
c, router := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "", nil)
templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
router.SetHTMLTemplate(templ)
@ -1461,7 +1502,7 @@ func TestContextNegotiationWithHTML(t *testing.T) {
func TestContextNegotiationNotSupport(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "", nil)
c.Negotiate(http.StatusOK, Negotiate{
Offered: []string{MIMEPOSTForm},
@ -1474,7 +1515,7 @@ func TestContextNegotiationNotSupport(t *testing.T) {
func TestContextNegotiationFormat(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "", nil)
assert.Panics(t, func() { c.NegotiateFormat() })
assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML))
@ -1483,7 +1524,7 @@ func TestContextNegotiationFormat(t *testing.T) {
func TestContextNegotiationFormatWithAccept(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "/", nil)
c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8")
assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEJSON, MIMEXML))
@ -1493,7 +1534,7 @@ func TestContextNegotiationFormatWithAccept(t *testing.T) {
func TestContextNegotiationFormatWithWildcardAccept(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "/", nil)
c.Request.Header.Add("Accept", "*/*")
assert.Equal(t, "*/*", c.NegotiateFormat("*/*"))
@ -1504,7 +1545,7 @@ func TestContextNegotiationFormatWithWildcardAccept(t *testing.T) {
assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEHTML))
c, _ = CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "/", nil)
c.Request.Header.Add("Accept", "text/*")
assert.Equal(t, "*/*", c.NegotiateFormat("*/*"))
@ -1517,7 +1558,7 @@ func TestContextNegotiationFormatWithWildcardAccept(t *testing.T) {
func TestContextNegotiationFormatCustom(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "/", nil)
c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8")
c.Accepted = nil
@ -1530,7 +1571,7 @@ func TestContextNegotiationFormatCustom(t *testing.T) {
func TestContextNegotiationFormat2(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "/", nil)
c.Request.Header.Add("Accept", "image/tiff-fx")
assert.Equal(t, "", c.NegotiateFormat("image/tiff"))
@ -1658,7 +1699,7 @@ func TestContextAbortWithError(t *testing.T) {
func TestContextClientIP(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "/", nil)
c.engine.trustedCIDRs, _ = c.engine.prepareTrustedCIDRs()
resetContextForClientIPTests(c)
@ -1801,7 +1842,7 @@ func resetContextForClientIPTests(c *Context) {
func TestContextContentType(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "/", nil)
c.Request.Header.Set("Content-Type", "application/json; charset=utf-8")
assert.Equal(t, "application/json", c.ContentType())
@ -1809,7 +1850,7 @@ func TestContextContentType(t *testing.T) {
func TestContextAutoBindJSON(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
c.Request.Header.Add("Content-Type", MIMEJSON)
var obj struct {
@ -1826,7 +1867,7 @@ func TestContextBindWithJSON(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
var obj struct {
@ -1843,7 +1884,7 @@ func TestContextBindWithXML(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
<root>
<foo>FOO</foo>
<bar>BAR</bar>
@ -1864,7 +1905,7 @@ func TestContextBindPlain(t *testing.T) {
// string
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`test string`))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(`test string`))
c.Request.Header.Add("Content-Type", MIMEPlain)
var s string
@ -1874,7 +1915,7 @@ func TestContextBindPlain(t *testing.T) {
assert.Equal(t, 0, w.Body.Len())
// []byte
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`test []byte`))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(`test []byte`))
c.Request.Header.Add("Content-Type", MIMEPlain)
var bs []byte
@ -1888,7 +1929,7 @@ func TestContextBindHeader(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "/", nil)
c.Request.Header.Add("rate", "8000")
c.Request.Header.Add("domain", "music")
c.Request.Header.Add("limit", "1000")
@ -1910,7 +1951,7 @@ func TestContextBindWithQuery(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/?foo=bar&bar=foo", bytes.NewBufferString("foo=unused"))
c.Request, _ = http.NewRequest(http.MethodPost, "/?foo=bar&bar=foo", bytes.NewBufferString("foo=unused"))
var obj struct {
Foo string `form:"foo"`
@ -1926,7 +1967,7 @@ func TestContextBindWithYAML(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("foo: bar\nbar: foo"))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("foo: bar\nbar: foo"))
c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
var obj struct {
@ -1943,7 +1984,7 @@ func TestContextBindWithTOML(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("foo = 'bar'\nbar = 'foo'"))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("foo = 'bar'\nbar = 'foo'"))
c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
var obj struct {
@ -1960,7 +2001,7 @@ func TestContextBadAutoBind(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "http://example.com", bytes.NewBufferString("\"foo\":\"bar\", \"bar\":\"foo\"}"))
c.Request, _ = http.NewRequest(http.MethodPost, "http://example.com", bytes.NewBufferString("\"foo\":\"bar\", \"bar\":\"foo\"}"))
c.Request.Header.Add("Content-Type", MIMEJSON)
var obj struct {
Foo string `json:"foo"`
@ -1979,7 +2020,7 @@ func TestContextBadAutoBind(t *testing.T) {
func TestContextAutoShouldBindJSON(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
c.Request.Header.Add("Content-Type", MIMEJSON)
var obj struct {
@ -1996,7 +2037,7 @@ func TestContextShouldBindWithJSON(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
var obj struct {
@ -2013,7 +2054,7 @@ func TestContextShouldBindWithXML(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
<root>
<foo>FOO</foo>
<bar>BAR</bar>
@ -2034,7 +2075,7 @@ func TestContextShouldBindPlain(t *testing.T) {
// string
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`test string`))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(`test string`))
c.Request.Header.Add("Content-Type", MIMEPlain)
var s string
@ -2044,7 +2085,7 @@ func TestContextShouldBindPlain(t *testing.T) {
assert.Equal(t, 0, w.Body.Len())
// []byte
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`test []byte`))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(`test []byte`))
c.Request.Header.Add("Content-Type", MIMEPlain)
var bs []byte
@ -2058,7 +2099,7 @@ func TestContextShouldBindHeader(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "/", nil)
c.Request.Header.Add("rate", "8000")
c.Request.Header.Add("domain", "music")
c.Request.Header.Add("limit", "1000")
@ -2080,7 +2121,7 @@ func TestContextShouldBindWithQuery(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/?foo=bar&bar=foo&Foo=bar1&Bar=foo1", bytes.NewBufferString("foo=unused"))
c.Request, _ = http.NewRequest(http.MethodPost, "/?foo=bar&bar=foo&Foo=bar1&Bar=foo1", bytes.NewBufferString("foo=unused"))
var obj struct {
Foo string `form:"foo"`
@ -2100,7 +2141,7 @@ func TestContextShouldBindWithYAML(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("foo: bar\nbar: foo"))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("foo: bar\nbar: foo"))
c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
var obj struct {
@ -2117,7 +2158,7 @@ func TestContextShouldBindWithTOML(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("foo='bar'\nbar= 'foo'"))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("foo='bar'\nbar= 'foo'"))
c.Request.Header.Add("Content-Type", MIMETOML) // set fake content-type
var obj struct {
@ -2134,7 +2175,7 @@ func TestContextBadAutoShouldBind(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "http://example.com", bytes.NewBufferString("\"foo\":\"bar\", \"bar\":\"foo\"}"))
c.Request, _ = http.NewRequest(http.MethodPost, "http://example.com", bytes.NewBufferString("\"foo\":\"bar\", \"bar\":\"foo\"}"))
c.Request.Header.Add("Content-Type", MIMEJSON)
var obj struct {
Foo string `json:"foo"`
@ -2198,7 +2239,7 @@ func TestContextShouldBindBodyWith(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest(
"POST", "http://example.com", bytes.NewBufferString(tt.bodyA),
http.MethodPost, "http://example.com", bytes.NewBufferString(tt.bodyA),
)
// When it binds to typeA and typeB, it finds the body is
// not typeB but typeA.
@ -2216,7 +2257,7 @@ func TestContextShouldBindBodyWith(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest(
"POST", "http://example.com", bytes.NewBufferString(tt.bodyB),
http.MethodPost, "http://example.com", bytes.NewBufferString(tt.bodyB),
)
objA := typeA{}
require.Error(t, c.ShouldBindBodyWith(&objA, tt.bindingA))
@ -2263,7 +2304,7 @@ func TestContextShouldBindBodyWithJSON(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(tt.body))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(tt.body))
type typeJSON struct {
Foo string `json:"foo" binding:"required"`
@ -2327,7 +2368,7 @@ func TestContextShouldBindBodyWithXML(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(tt.body))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(tt.body))
type typeXML struct {
Foo string `xml:"foo" binding:"required"`
@ -2391,7 +2432,7 @@ func TestContextShouldBindBodyWithYAML(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(tt.body))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(tt.body))
type typeYAML struct {
Foo string `yaml:"foo" binding:"required"`
@ -2456,7 +2497,7 @@ func TestContextShouldBindBodyWithTOML(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(tt.body))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(tt.body))
type typeTOML struct {
Foo string `toml:"foo" binding:"required"`
@ -2525,7 +2566,7 @@ func TestContextShouldBindBodyWithPlain(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(tt.body))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(tt.body))
type typeJSON struct {
Foo string `json:"foo" binding:"required"`
@ -2562,7 +2603,7 @@ func TestContextShouldBindBodyWithPlain(t *testing.T) {
func TestContextGolangContext(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
require.NoError(t, c.Err())
assert.Nil(t, c.Done())
ti, ok := c.Deadline()
@ -2580,7 +2621,7 @@ func TestContextGolangContext(t *testing.T) {
func TestWebsocketsRequired(t *testing.T) {
// Example request from spec: https://tools.ietf.org/html/rfc6455#section-1.2
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("GET", "/chat", nil)
c.Request, _ = http.NewRequest(http.MethodGet, "/chat", nil)
c.Request.Header.Set("Host", "server.example.com")
c.Request.Header.Set("Upgrade", "websocket")
c.Request.Header.Set("Connection", "Upgrade")
@ -2593,7 +2634,7 @@ func TestWebsocketsRequired(t *testing.T) {
// Normal request, no websocket required.
c, _ = CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("GET", "/chat", nil)
c.Request, _ = http.NewRequest(http.MethodGet, "/chat", nil)
c.Request.Header.Set("Host", "server.example.com")
assert.False(t, c.IsWebsocket())
@ -2601,7 +2642,7 @@ func TestWebsocketsRequired(t *testing.T) {
func TestGetRequestHeaderValue(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("GET", "/chat", nil)
c.Request, _ = http.NewRequest(http.MethodGet, "/chat", nil)
c.Request.Header.Set("Gin-Version", "1.0.0")
assert.Equal(t, "1.0.0", c.GetHeader("Gin-Version"))
@ -2611,7 +2652,7 @@ func TestGetRequestHeaderValue(t *testing.T) {
func TestContextGetRawData(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
body := bytes.NewBufferString("Fetch binary post data")
c.Request, _ = http.NewRequest("POST", "/", body)
c.Request, _ = http.NewRequest(http.MethodPost, "/", body)
c.Request.Header.Add("Content-Type", MIMEPOSTForm)
data, err := c.GetRawData()
@ -2634,7 +2675,7 @@ func TestContextRenderDataFromReader(t *testing.T) {
assert.Equal(t, http.StatusOK, w.Code)
assert.Equal(t, body, w.Body.String())
assert.Equal(t, contentType, w.Header().Get("Content-Type"))
assert.Equal(t, fmt.Sprintf("%d", contentLength), w.Header().Get("Content-Length"))
assert.Equal(t, strconv.FormatInt(contentLength, 10), w.Header().Get("Content-Length"))
assert.Equal(t, extraHeaders["Content-Disposition"], w.Header().Get("Content-Disposition"))
}
@ -2652,7 +2693,7 @@ func TestContextRenderDataFromReaderNoHeaders(t *testing.T) {
assert.Equal(t, http.StatusOK, w.Code)
assert.Equal(t, body, w.Body.String())
assert.Equal(t, contentType, w.Header().Get("Content-Type"))
assert.Equal(t, fmt.Sprintf("%d", contentLength), w.Header().Get("Content-Length"))
assert.Equal(t, strconv.FormatInt(contentLength, 10), w.Header().Get("Content-Length"))
}
type TestResponseRecorder struct {
@ -2740,8 +2781,8 @@ func TestRaceParamsContextCopy(t *testing.T) {
}(c.Copy(), c.Param("name"))
})
}
PerformRequest(router, "GET", "/name1/api")
PerformRequest(router, "GET", "/name2/api")
PerformRequest(router, http.MethodGet, "/name1/api")
PerformRequest(router, http.MethodGet, "/name2/api")
wg.Wait()
}
@ -2760,7 +2801,7 @@ func TestContextWithKeysMutex(t *testing.T) {
func TestRemoteIPFail(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "/", nil)
c.Request.RemoteAddr = "[:::]:80"
ip := net.ParseIP(c.RemoteIP())
trust := c.engine.isTrustedProxy(ip)
@ -2862,7 +2903,7 @@ func TestContextWithFallbackValueFromRequestContext(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
// enable ContextWithFallback feature flag
c.engine.ContextWithFallback = true
c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "/", nil)
c.Request = c.Request.WithContext(context.WithValue(context.TODO(), key, "value"))
return c, key
},
@ -2874,7 +2915,7 @@ func TestContextWithFallbackValueFromRequestContext(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
// enable ContextWithFallback feature flag
c.engine.ContextWithFallback = true
c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "/", nil)
c.Request = c.Request.WithContext(context.WithValue(context.TODO(), contextKey("key"), "value"))
return c, contextKey("key")
},
@ -2897,7 +2938,7 @@ func TestContextWithFallbackValueFromRequestContext(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
// enable ContextWithFallback feature flag
c.engine.ContextWithFallback = true
c.Request, _ = http.NewRequest("POST", "/", nil)
c.Request, _ = http.NewRequest(http.MethodPost, "/", nil)
return c, "key"
},
value: nil,
@ -3029,7 +3070,7 @@ func TestInterceptedHeader(t *testing.T) {
c.Header("X-Test-2", "present")
c.String(http.StatusOK, "hello world")
})
c.Request = httptest.NewRequest("GET", "/", nil)
c.Request = httptest.NewRequest(http.MethodGet, "/", 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
@ -3038,3 +3079,47 @@ func TestInterceptedHeader(t *testing.T) {
assert.Equal(t, "", w.Result().Header.Get("X-Test"))
assert.Equal(t, "present", w.Result().Header.Get("X-Test-2"))
}
func TestContextNext(t *testing.T) {
c, _ := CreateTestContext(httptest.NewRecorder())
// Test with no handlers
c.Next()
assert.Equal(t, int8(0), c.index)
// Test with one handler
c.index = -1
c.handlers = HandlersChain{func(c *Context) {
c.Set("key", "value")
}}
c.Next()
assert.Equal(t, int8(1), c.index)
value, exists := c.Get("key")
assert.True(t, exists)
assert.Equal(t, "value", value)
// Test with multiple handlers
c.handlers = HandlersChain{
func(c *Context) {
c.Set("key1", "value1")
c.Next()
c.Set("key2", "value2")
},
nil,
func(c *Context) {
c.Set("key3", "value3")
},
}
c.index = -1
c.Next()
assert.Equal(t, int8(4), c.index)
value, exists = c.Get("key1")
assert.True(t, exists)
assert.Equal(t, "value1", value)
value, exists = c.Get("key2")
assert.True(t, exists)
assert.Equal(t, "value2", value)
value, exists = c.Get("key3")
assert.True(t, exists)
assert.Equal(t, "value3", value)
}

View File

@ -10,6 +10,7 @@ import (
"html/template"
"io"
"log"
"net/http"
"os"
"runtime"
"strings"
@ -60,7 +61,7 @@ func TestDebugPrintError(t *testing.T) {
func TestDebugPrintRoutes(t *testing.T) {
re := captureOutput(t, func() {
SetMode(DebugMode)
debugPrintRoute("GET", "/path/to/route/:param", HandlersChain{func(c *Context) {}, handlerNameTest})
debugPrintRoute(http.MethodGet, "/path/to/route/:param", HandlersChain{func(c *Context) {}, handlerNameTest})
SetMode(TestMode)
})
assert.Regexp(t, `^\[GIN-debug\] GET /path/to/route/:param --> (.*/vendor/)?github.com/gin-gonic/gin.handlerNameTest \(2 handlers\)\n$`, re)
@ -72,7 +73,7 @@ func TestDebugPrintRouteFunc(t *testing.T) {
}
re := captureOutput(t, func() {
SetMode(DebugMode)
debugPrintRoute("GET", "/path/to/route/:param1/:param2", HandlersChain{func(c *Context) {}, handlerNameTest})
debugPrintRoute(http.MethodGet, "/path/to/route/:param1/:param2", HandlersChain{func(c *Context) {}, handlerNameTest})
SetMode(TestMode)
})
assert.Regexp(t, `^\[GIN-debug\] GET /path/to/route/:param1/:param2 --> (.*/vendor/)?github.com/gin-gonic/gin.handlerNameTest \(2 handlers\)\n$`, re)

View File

@ -18,7 +18,7 @@ func TestBindWith(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request, _ = http.NewRequest("POST", "/?foo=bar&bar=foo", bytes.NewBufferString("foo=unused"))
c.Request, _ = http.NewRequest(http.MethodPost, "/?foo=bar&bar=foo", bytes.NewBufferString("foo=unused"))
var obj struct {
Foo string `form:"foo"`

View File

@ -0,0 +1,18 @@
package errorparser
func ParseBindError(err error) (errs []ParseError, match bool) {
if errs, ok := parseValidatorError(err); ok {
return errs, true
}
if errs, ok := parseJsonDecodeError(err); ok {
return errs, true
}
// todo: protobuf
// todo: xml
// todo: yaml
return nil, false
}

View File

@ -0,0 +1,23 @@
package errorparser
import (
"encoding/json"
"fmt"
"testing"
"github.com/go-playground/validator/v10"
"github.com/stretchr/testify/assert"
)
func TestParseBindError(t *testing.T) {
_, ok := ParseBindError(fmt.Errorf("not match"))
assert.False(t, ok)
_, ok = ParseBindError(validator.ValidationErrors([]validator.FieldError{}))
assert.True(t, ok)
_, ok = ParseBindError(&json.SyntaxError{})
assert.True(t, ok)
}

View File

@ -0,0 +1,48 @@
package errorparser
import (
"encoding/json"
)
func parseJsonDecodeError(err error) (errs []ParseError, match bool) {
if typeErr, ok := err.(*json.UnmarshalTypeError); ok {
return parseJsonUnmarshalTypeError(typeErr), true
}
if syntaxErr, ok := err.(*json.SyntaxError); ok {
return parseJsonSyntaxError(syntaxErr), true
}
return nil, false
}
func parseJsonUnmarshalTypeError(err *json.UnmarshalTypeError) (errs []ParseError) {
errs = []ParseError{}
item := NewParseError(
err.Field,
ParseErrorTypeMismatch,
err,
)
errs = append(errs, item)
return errs
}
func parseJsonSyntaxError(err *json.SyntaxError) (errs []ParseError) {
errs = []ParseError{}
item := NewParseError(
"",
ParseErrorTypeBadInput,
err,
)
errs = append(errs, item)
return errs
}

View File

@ -0,0 +1,94 @@
package errorparser
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/gin-gonic/gin"
)
func TestParseJsonDecodeError(t *testing.T) {
_, ok := parseJsonDecodeError(fmt.Errorf("not match"))
assert.False(t, ok)
_, ok = parseJsonDecodeError(&json.UnmarshalTypeError{})
assert.True(t, ok)
_, ok = parseJsonDecodeError(&json.SyntaxError{})
assert.True(t, ok)
}
func TestParseJsonUnmarshalTypeError(t *testing.T) {
jsonData := `{
"text": "text",
"count": "1"
}`
rbody := bytes.NewReader([]byte(jsonData))
c, _ := gin.CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", rbody)
c.Request.Header.Add("Content-Type", gin.MIMEJSON)
var obj struct {
Text string `json:"text"`
Count int `json:"count"`
}
err := c.Bind(&obj)
require.Error(t, err)
typeErr, ok := err.(*json.UnmarshalTypeError)
require.True(t, ok)
parseErrs := parseJsonUnmarshalTypeError(typeErr)
require.Equal(t, len(parseErrs), 1)
assert.Equal(t, parseErrs[0].ParamName, "count")
assert.Equal(t, parseErrs[0].ErrorType, ParseErrorTypeMismatch)
assert.Equal(t, parseErrs[0].InitialError, err)
}
func TestParseJsonSyntaxError(t *testing.T) {
jsonData := `{
"text": "text"
"count": 1
}`
rbody := bytes.NewReader([]byte(jsonData))
c, _ := gin.CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", rbody)
c.Request.Header.Add("Content-Type", gin.MIMEJSON)
var obj struct {
Text string `json:"text"`
Count int `json:"count"`
}
err := c.Bind(&obj)
require.Error(t, err)
typeErr, ok := err.(*json.SyntaxError)
require.True(t, ok)
parseErrs := parseJsonSyntaxError(typeErr)
require.Equal(t, len(parseErrs), 1)
assert.Equal(t, parseErrs[0].ParamName, "")
assert.Equal(t, parseErrs[0].ErrorType, ParseErrorTypeBadInput)
assert.Equal(t, parseErrs[0].InitialError, err)
}

View File

@ -0,0 +1,28 @@
package errorparser
type ParseError struct {
ParamName string
ErrorType ParseErrorType
InitialError error
}
func NewParseError(
paramName string,
errorType ParseErrorType,
initialError error,
) ParseError {
return ParseError{
ParamName: paramName,
ErrorType: errorType,
InitialError: initialError,
}
}
type ParseErrorType string
const (
ParseErrorTypeNone ParseErrorType = ""
ParseErrorTypeBadInput ParseErrorType = "bad_input"
ParseErrorTypeMismatch ParseErrorType = "type_mismatch"
ParseErrorTypeValidation ParseErrorType = "validation"
)

View File

@ -0,0 +1,27 @@
package errorparser
import (
"github.com/go-playground/validator/v10"
)
func parseValidatorError(err error) (errs []ParseError, match bool) {
if vErr, ok := err.(validator.ValidationErrors); ok {
return parseValidatorValidationErrors(vErr), true
}
return nil, false
}
func parseValidatorValidationErrors(vErr validator.ValidationErrors) (errs []ParseError) {
fErrs := []validator.FieldError(vErr)
errs = make([]ParseError, 0, len(fErrs))
for _, fErr := range fErrs {
item := NewParseError(
fErr.Field(),
ParseErrorTypeValidation,
fErr,
)
errs = append(errs, item)
}
return errs
}

View File

@ -0,0 +1,61 @@
package errorparser
import (
"bytes"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"github.com/go-playground/validator/v10"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/gin-gonic/gin"
)
func TestParseValidatorError(t *testing.T) {
_, ok := parseValidatorError(fmt.Errorf("not match"))
assert.False(t, ok)
_, ok = parseValidatorError(validator.ValidationErrors{})
assert.True(t, ok)
}
func TestParseValidatorValidationErrors(t *testing.T) {
jsonData := `{
"text": "",
"count": 1
}`
rbody := bytes.NewReader([]byte(jsonData))
c, _ := gin.CreateTestContext(httptest.NewRecorder())
c.Request, _ = http.NewRequest("POST", "/", rbody)
c.Request.Header.Add("Content-Type", gin.MIMEJSON)
var obj struct {
Text string `json:"text" binding:"required"`
Count int `json:"count"`
}
err := c.Bind(&obj)
require.Error(t, err)
vErr, ok := err.(validator.ValidationErrors)
require.True(t, ok)
fErrs := []validator.FieldError(vErr)
require.Equal(t, len(fErrs), 1)
parseErrs := parseValidatorValidationErrors(vErr)
require.Equal(t, len(parseErrs), 1)
assert.Equal(t, parseErrs[0].ParamName, fErrs[0].Field())
assert.Equal(t, parseErrs[0].ErrorType, ParseErrorTypeValidation)
assert.Equal(t, parseErrs[0].InitialError, fErrs[0])
}

View File

@ -73,7 +73,7 @@ func TestLoadHTMLGlobDebugMode(t *testing.T) {
)
defer ts.Close()
res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
res, err := http.Get(ts.URL + "/test")
if err != nil {
t.Error(err)
}
@ -131,7 +131,7 @@ func TestLoadHTMLGlobTestMode(t *testing.T) {
)
defer ts.Close()
res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
res, err := http.Get(ts.URL + "/test")
if err != nil {
t.Error(err)
}
@ -151,7 +151,7 @@ func TestLoadHTMLGlobReleaseMode(t *testing.T) {
)
defer ts.Close()
res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
res, err := http.Get(ts.URL + "/test")
if err != nil {
t.Error(err)
}
@ -178,7 +178,7 @@ func TestLoadHTMLGlobUsingTLS(t *testing.T) {
},
}
client := &http.Client{Transport: tr}
res, err := client.Get(fmt.Sprintf("%s/test", ts.URL))
res, err := client.Get(ts.URL + "/test")
if err != nil {
t.Error(err)
}
@ -198,7 +198,7 @@ func TestLoadHTMLGlobFromFuncMap(t *testing.T) {
)
defer ts.Close()
res, err := http.Get(fmt.Sprintf("%s/raw", ts.URL))
res, err := http.Get(ts.URL + "/raw")
if err != nil {
t.Error(err)
}
@ -229,7 +229,7 @@ func TestLoadHTMLFilesTestMode(t *testing.T) {
)
defer ts.Close()
res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
res, err := http.Get(ts.URL + "/test")
if err != nil {
t.Error(err)
}
@ -249,7 +249,7 @@ func TestLoadHTMLFilesDebugMode(t *testing.T) {
)
defer ts.Close()
res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
res, err := http.Get(ts.URL + "/test")
if err != nil {
t.Error(err)
}
@ -269,7 +269,7 @@ func TestLoadHTMLFilesReleaseMode(t *testing.T) {
)
defer ts.Close()
res, err := http.Get(fmt.Sprintf("%s/test", ts.URL))
res, err := http.Get(ts.URL + "/test")
if err != nil {
t.Error(err)
}
@ -296,7 +296,7 @@ func TestLoadHTMLFilesUsingTLS(t *testing.T) {
},
}
client := &http.Client{Transport: tr}
res, err := client.Get(fmt.Sprintf("%s/test", ts.URL))
res, err := client.Get(ts.URL + "/test")
if err != nil {
t.Error(err)
}
@ -316,7 +316,7 @@ func TestLoadHTMLFilesFuncMap(t *testing.T) {
)
defer ts.Close()
res, err := http.Get(fmt.Sprintf("%s/raw", ts.URL))
res, err := http.Get(ts.URL + "/raw")
if err != nil {
t.Error(err)
}
@ -327,31 +327,31 @@ func TestLoadHTMLFilesFuncMap(t *testing.T) {
func TestAddRoute(t *testing.T) {
router := New()
router.addRoute("GET", "/", HandlersChain{func(_ *Context) {}})
router.addRoute(http.MethodGet, "/", HandlersChain{func(_ *Context) {}})
assert.Len(t, router.trees, 1)
assert.NotNil(t, router.trees.get("GET"))
assert.Nil(t, router.trees.get("POST"))
assert.NotNil(t, router.trees.get(http.MethodGet))
assert.Nil(t, router.trees.get(http.MethodPost))
router.addRoute("POST", "/", HandlersChain{func(_ *Context) {}})
router.addRoute(http.MethodPost, "/", HandlersChain{func(_ *Context) {}})
assert.Len(t, router.trees, 2)
assert.NotNil(t, router.trees.get("GET"))
assert.NotNil(t, router.trees.get("POST"))
assert.NotNil(t, router.trees.get(http.MethodGet))
assert.NotNil(t, router.trees.get(http.MethodPost))
router.addRoute("POST", "/post", HandlersChain{func(_ *Context) {}})
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("GET", "a", HandlersChain{func(_ *Context) {}}) })
assert.Panics(t, func() { router.addRoute("GET", "/", HandlersChain{}) })
assert.Panics(t, func() { router.addRoute(http.MethodGet, "a", HandlersChain{func(_ *Context) {}}) })
assert.Panics(t, func() { router.addRoute(http.MethodGet, "/", HandlersChain{}) })
router.addRoute("POST", "/post", HandlersChain{func(_ *Context) {}})
router.addRoute(http.MethodPost, "/post", HandlersChain{func(_ *Context) {}})
assert.Panics(t, func() {
router.addRoute("POST", "/post", HandlersChain{func(_ *Context) {}})
router.addRoute(http.MethodPost, "/post", HandlersChain{func(_ *Context) {}})
})
}
@ -493,27 +493,27 @@ func TestListOfRoutes(t *testing.T) {
assert.Len(t, list, 7)
assertRoutePresent(t, list, RouteInfo{
Method: "GET",
Method: http.MethodGet,
Path: "/favicon.ico",
Handler: "^(.*/vendor/)?github.com/gin-gonic/gin.handlerTest1$",
})
assertRoutePresent(t, list, RouteInfo{
Method: "GET",
Method: http.MethodGet,
Path: "/",
Handler: "^(.*/vendor/)?github.com/gin-gonic/gin.handlerTest1$",
})
assertRoutePresent(t, list, RouteInfo{
Method: "GET",
Method: http.MethodGet,
Path: "/users/",
Handler: "^(.*/vendor/)?github.com/gin-gonic/gin.handlerTest2$",
})
assertRoutePresent(t, list, RouteInfo{
Method: "GET",
Method: http.MethodGet,
Path: "/users/:id",
Handler: "^(.*/vendor/)?github.com/gin-gonic/gin.handlerTest1$",
})
assertRoutePresent(t, list, RouteInfo{
Method: "POST",
Method: http.MethodPost,
Path: "/users/:id",
Handler: "^(.*/vendor/)?github.com/gin-gonic/gin.handlerTest2$",
})
@ -531,7 +531,7 @@ func TestEngineHandleContext(t *testing.T) {
}
assert.NotPanics(t, func() {
w := PerformRequest(r, "GET", "/")
w := PerformRequest(r, http.MethodGet, "/")
assert.Equal(t, 301, w.Code)
})
}
@ -564,7 +564,7 @@ func TestEngineHandleContextManyReEntries(t *testing.T) {
})
assert.NotPanics(t, func() {
w := PerformRequest(r, "GET", "/"+strconv.Itoa(expectValue-1)) // include 0 value
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())
})
@ -712,8 +712,8 @@ func TestNewOptionFunc(t *testing.T) {
r := New(fc)
routes := r.Routes()
assertRoutePresent(t, routes, RouteInfo{Path: "/test1", Method: "GET", Handler: "github.com/gin-gonic/gin.handlerTest1"})
assertRoutePresent(t, routes, RouteInfo{Path: "/test2", Method: "GET", Handler: "github.com/gin-gonic/gin.handlerTest2"})
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) {
@ -729,8 +729,8 @@ func TestWithOptionFunc(t *testing.T) {
})
routes := r.Routes()
assertRoutePresent(t, routes, RouteInfo{Path: "/test1", Method: "GET", Handler: "github.com/gin-gonic/gin.handlerTest1"})
assertRoutePresent(t, routes, RouteInfo{Path: "/test2", Method: "GET", Handler: "github.com/gin-gonic/gin.handlerTest2"})
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
@ -749,7 +749,7 @@ func TestCustomUnmarshalStruct(t *testing.T) {
_ = ctx.BindQuery(&request)
ctx.JSON(200, request.Birthday)
})
req := httptest.NewRequest("GET", "/test?birthday=2000-01-01", nil)
req := httptest.NewRequest(http.MethodGet, "/test?birthday=2000-01-01", nil)
w := httptest.NewRecorder()
route.ServeHTTP(w, req)
assert.Equal(t, 200, w.Code)
@ -761,7 +761,7 @@ func TestMethodNotAllowedNoRoute(t *testing.T) {
g := New()
g.HandleMethodNotAllowed = true
req := httptest.NewRequest("GET", "/", nil)
req := httptest.NewRequest(http.MethodGet, "/", nil)
resp := httptest.NewRecorder()
assert.NotPanics(t, func() { g.ServeHTTP(resp, req) })
assert.Equal(t, http.StatusNotFound, resp.Code)

View File

@ -10,6 +10,7 @@ import (
"net/http"
"net/http/httptest"
"os"
"strconv"
"strings"
"testing"
@ -411,7 +412,7 @@ func exampleFromPath(path string) (string, Params) {
}
if start >= 0 {
if c == '/' {
value := fmt.Sprint(rand.Intn(100000))
value := strconv.Itoa(rand.Intn(100000))
params = append(params, Param{
Key: path[start:i],
Value: value,
@ -425,7 +426,7 @@ func exampleFromPath(path string) (string, Params) {
}
}
if start >= 0 {
value := fmt.Sprint(rand.Intn(100000))
value := strconv.Itoa(rand.Intn(100000))
params = append(params, Param{
Key: path[start:],
Value: value,

View File

@ -31,9 +31,9 @@ func TestLogger(t *testing.T) {
router.HEAD("/example", func(c *Context) {})
router.OPTIONS("/example", func(c *Context) {})
PerformRequest(router, "GET", "/example?a=100")
PerformRequest(router, http.MethodGet, "/example?a=100")
assert.Contains(t, buffer.String(), "200")
assert.Contains(t, buffer.String(), "GET")
assert.Contains(t, buffer.String(), http.MethodGet)
assert.Contains(t, buffer.String(), "/example")
assert.Contains(t, buffer.String(), "a=100")
@ -41,21 +41,21 @@ func TestLogger(t *testing.T) {
// like integration tests because they test the whole logging process rather
// than individual functions. Im not sure where these should go.
buffer.Reset()
PerformRequest(router, "POST", "/example")
PerformRequest(router, http.MethodPost, "/example")
assert.Contains(t, buffer.String(), "200")
assert.Contains(t, buffer.String(), "POST")
assert.Contains(t, buffer.String(), http.MethodPost)
assert.Contains(t, buffer.String(), "/example")
buffer.Reset()
PerformRequest(router, "PUT", "/example")
PerformRequest(router, http.MethodPut, "/example")
assert.Contains(t, buffer.String(), "200")
assert.Contains(t, buffer.String(), "PUT")
assert.Contains(t, buffer.String(), http.MethodPut)
assert.Contains(t, buffer.String(), "/example")
buffer.Reset()
PerformRequest(router, "DELETE", "/example")
PerformRequest(router, http.MethodDelete, "/example")
assert.Contains(t, buffer.String(), "200")
assert.Contains(t, buffer.String(), "DELETE")
assert.Contains(t, buffer.String(), http.MethodDelete)
assert.Contains(t, buffer.String(), "/example")
buffer.Reset()
@ -77,9 +77,9 @@ func TestLogger(t *testing.T) {
assert.Contains(t, buffer.String(), "/example")
buffer.Reset()
PerformRequest(router, "GET", "/notfound")
PerformRequest(router, http.MethodGet, "/notfound")
assert.Contains(t, buffer.String(), "404")
assert.Contains(t, buffer.String(), "GET")
assert.Contains(t, buffer.String(), http.MethodGet)
assert.Contains(t, buffer.String(), "/notfound")
}
@ -95,9 +95,9 @@ func TestLoggerWithConfig(t *testing.T) {
router.HEAD("/example", func(c *Context) {})
router.OPTIONS("/example", func(c *Context) {})
PerformRequest(router, "GET", "/example?a=100")
PerformRequest(router, http.MethodGet, "/example?a=100")
assert.Contains(t, buffer.String(), "200")
assert.Contains(t, buffer.String(), "GET")
assert.Contains(t, buffer.String(), http.MethodGet)
assert.Contains(t, buffer.String(), "/example")
assert.Contains(t, buffer.String(), "a=100")
@ -105,21 +105,21 @@ func TestLoggerWithConfig(t *testing.T) {
// like integration tests because they test the whole logging process rather
// than individual functions. Im not sure where these should go.
buffer.Reset()
PerformRequest(router, "POST", "/example")
PerformRequest(router, http.MethodPost, "/example")
assert.Contains(t, buffer.String(), "200")
assert.Contains(t, buffer.String(), "POST")
assert.Contains(t, buffer.String(), http.MethodPost)
assert.Contains(t, buffer.String(), "/example")
buffer.Reset()
PerformRequest(router, "PUT", "/example")
PerformRequest(router, http.MethodPut, "/example")
assert.Contains(t, buffer.String(), "200")
assert.Contains(t, buffer.String(), "PUT")
assert.Contains(t, buffer.String(), http.MethodPut)
assert.Contains(t, buffer.String(), "/example")
buffer.Reset()
PerformRequest(router, "DELETE", "/example")
PerformRequest(router, http.MethodDelete, "/example")
assert.Contains(t, buffer.String(), "200")
assert.Contains(t, buffer.String(), "DELETE")
assert.Contains(t, buffer.String(), http.MethodDelete)
assert.Contains(t, buffer.String(), "/example")
buffer.Reset()
@ -141,9 +141,9 @@ func TestLoggerWithConfig(t *testing.T) {
assert.Contains(t, buffer.String(), "/example")
buffer.Reset()
PerformRequest(router, "GET", "/notfound")
PerformRequest(router, http.MethodGet, "/notfound")
assert.Contains(t, buffer.String(), "404")
assert.Contains(t, buffer.String(), "GET")
assert.Contains(t, buffer.String(), http.MethodGet)
assert.Contains(t, buffer.String(), "/notfound")
}
@ -169,12 +169,12 @@ func TestLoggerWithFormatter(t *testing.T) {
)
}))
router.GET("/example", func(c *Context) {})
PerformRequest(router, "GET", "/example?a=100")
PerformRequest(router, http.MethodGet, "/example?a=100")
// output test
assert.Contains(t, buffer.String(), "[FORMATTER TEST]")
assert.Contains(t, buffer.String(), "200")
assert.Contains(t, buffer.String(), "GET")
assert.Contains(t, buffer.String(), http.MethodGet)
assert.Contains(t, buffer.String(), "/example")
assert.Contains(t, buffer.String(), "a=100")
}
@ -210,12 +210,12 @@ func TestLoggerWithConfigFormatting(t *testing.T) {
gotKeys = c.Keys
time.Sleep(time.Millisecond)
})
PerformRequest(router, "GET", "/example?a=100")
PerformRequest(router, http.MethodGet, "/example?a=100")
// output test
assert.Contains(t, buffer.String(), "[FORMATTER TEST]")
assert.Contains(t, buffer.String(), "200")
assert.Contains(t, buffer.String(), "GET")
assert.Contains(t, buffer.String(), http.MethodGet)
assert.Contains(t, buffer.String(), "/example")
assert.Contains(t, buffer.String(), "a=100")
@ -225,7 +225,7 @@ func TestLoggerWithConfigFormatting(t *testing.T) {
assert.Equal(t, 200, gotParam.StatusCode)
assert.NotEmpty(t, gotParam.Latency)
assert.Equal(t, "20.20.20.20", gotParam.ClientIP)
assert.Equal(t, "GET", gotParam.Method)
assert.Equal(t, http.MethodGet, gotParam.Method)
assert.Equal(t, "/example?a=100", gotParam.Path)
assert.Empty(t, gotParam.ErrorMessage)
assert.Equal(t, gotKeys, gotParam.Keys)
@ -239,7 +239,7 @@ func TestDefaultLogFormatter(t *testing.T) {
StatusCode: 200,
Latency: time.Second * 5,
ClientIP: "20.20.20.20",
Method: "GET",
Method: http.MethodGet,
Path: "/",
ErrorMessage: "",
isTerm: false,
@ -250,7 +250,7 @@ func TestDefaultLogFormatter(t *testing.T) {
StatusCode: 200,
Latency: time.Second * 5,
ClientIP: "20.20.20.20",
Method: "GET",
Method: http.MethodGet,
Path: "/",
ErrorMessage: "",
isTerm: true,
@ -260,7 +260,7 @@ func TestDefaultLogFormatter(t *testing.T) {
StatusCode: 200,
Latency: time.Millisecond * 9876543210,
ClientIP: "20.20.20.20",
Method: "GET",
Method: http.MethodGet,
Path: "/",
ErrorMessage: "",
isTerm: true,
@ -271,7 +271,7 @@ func TestDefaultLogFormatter(t *testing.T) {
StatusCode: 200,
Latency: time.Millisecond * 9876543210,
ClientIP: "20.20.20.20",
Method: "GET",
Method: http.MethodGet,
Path: "/",
ErrorMessage: "",
isTerm: false,
@ -292,10 +292,10 @@ func TestColorForMethod(t *testing.T) {
return p.MethodColor()
}
assert.Equal(t, blue, colorForMethod("GET"), "get should be blue")
assert.Equal(t, cyan, colorForMethod("POST"), "post should be cyan")
assert.Equal(t, yellow, colorForMethod("PUT"), "put should be yellow")
assert.Equal(t, red, colorForMethod("DELETE"), "delete should be red")
assert.Equal(t, blue, colorForMethod(http.MethodGet), "get should be blue")
assert.Equal(t, cyan, colorForMethod(http.MethodPost), "post should be cyan")
assert.Equal(t, yellow, colorForMethod(http.MethodPut), "put should be yellow")
assert.Equal(t, red, colorForMethod(http.MethodDelete), "delete should be red")
assert.Equal(t, green, colorForMethod("PATCH"), "patch should be green")
assert.Equal(t, magenta, colorForMethod("HEAD"), "head should be magenta")
assert.Equal(t, white, colorForMethod("OPTIONS"), "options should be white")
@ -369,15 +369,15 @@ func TestErrorLogger(t *testing.T) {
c.String(http.StatusInternalServerError, "hola!")
})
w := PerformRequest(router, "GET", "/error")
w := PerformRequest(router, http.MethodGet, "/error")
assert.Equal(t, http.StatusOK, w.Code)
assert.Equal(t, "{\"error\":\"this is an error\"}", w.Body.String())
w = PerformRequest(router, "GET", "/abort")
w = PerformRequest(router, http.MethodGet, "/abort")
assert.Equal(t, http.StatusUnauthorized, w.Code)
assert.Equal(t, "{\"error\":\"no authorized\"}", w.Body.String())
w = PerformRequest(router, "GET", "/print")
w = PerformRequest(router, http.MethodGet, "/print")
assert.Equal(t, http.StatusInternalServerError, w.Code)
assert.Equal(t, "hola!{\"error\":\"this is an error\"}", w.Body.String())
}
@ -389,11 +389,11 @@ func TestLoggerWithWriterSkippingPaths(t *testing.T) {
router.GET("/logged", func(c *Context) {})
router.GET("/skipped", func(c *Context) {})
PerformRequest(router, "GET", "/logged")
PerformRequest(router, http.MethodGet, "/logged")
assert.Contains(t, buffer.String(), "200")
buffer.Reset()
PerformRequest(router, "GET", "/skipped")
PerformRequest(router, http.MethodGet, "/skipped")
assert.Contains(t, buffer.String(), "")
}
@ -407,11 +407,11 @@ func TestLoggerWithConfigSkippingPaths(t *testing.T) {
router.GET("/logged", func(c *Context) {})
router.GET("/skipped", func(c *Context) {})
PerformRequest(router, "GET", "/logged")
PerformRequest(router, http.MethodGet, "/logged")
assert.Contains(t, buffer.String(), "200")
buffer.Reset()
PerformRequest(router, "GET", "/skipped")
PerformRequest(router, http.MethodGet, "/skipped")
assert.Contains(t, buffer.String(), "")
}
@ -427,11 +427,11 @@ func TestLoggerWithConfigSkipper(t *testing.T) {
router.GET("/logged", func(c *Context) { c.Status(http.StatusOK) })
router.GET("/skipped", func(c *Context) { c.Status(http.StatusNoContent) })
PerformRequest(router, "GET", "/logged")
PerformRequest(router, http.MethodGet, "/logged")
assert.Contains(t, buffer.String(), "200")
buffer.Reset()
PerformRequest(router, "GET", "/skipped")
PerformRequest(router, http.MethodGet, "/skipped")
assert.Contains(t, buffer.String(), "")
}

View File

@ -35,7 +35,7 @@ func TestMiddlewareGeneralCase(t *testing.T) {
signature += " XX "
})
// RUN
w := PerformRequest(router, "GET", "/")
w := PerformRequest(router, http.MethodGet, "/")
// TEST
assert.Equal(t, http.StatusOK, w.Code)
@ -71,7 +71,7 @@ func TestMiddlewareNoRoute(t *testing.T) {
signature += " X "
})
// RUN
w := PerformRequest(router, "GET", "/")
w := PerformRequest(router, http.MethodGet, "/")
// TEST
assert.Equal(t, http.StatusNotFound, w.Code)
@ -108,7 +108,7 @@ func TestMiddlewareNoMethodEnabled(t *testing.T) {
signature += " XX "
})
// RUN
w := PerformRequest(router, "GET", "/")
w := PerformRequest(router, http.MethodGet, "/")
// TEST
assert.Equal(t, http.StatusMethodNotAllowed, w.Code)
@ -149,7 +149,7 @@ func TestMiddlewareNoMethodDisabled(t *testing.T) {
})
// RUN
w := PerformRequest(router, "GET", "/")
w := PerformRequest(router, http.MethodGet, "/")
// TEST
assert.Equal(t, http.StatusNotFound, w.Code)
@ -175,7 +175,7 @@ func TestMiddlewareAbort(t *testing.T) {
})
// RUN
w := PerformRequest(router, "GET", "/")
w := PerformRequest(router, http.MethodGet, "/")
// TEST
assert.Equal(t, http.StatusUnauthorized, w.Code)
@ -196,7 +196,7 @@ func TestMiddlewareAbortHandlersChainAndNext(t *testing.T) {
c.Next()
})
// RUN
w := PerformRequest(router, "GET", "/")
w := PerformRequest(router, http.MethodGet, "/")
// TEST
assert.Equal(t, http.StatusGone, w.Code)
@ -219,7 +219,7 @@ func TestMiddlewareFailHandlersChain(t *testing.T) {
signature += "C"
})
// RUN
w := PerformRequest(router, "GET", "/")
w := PerformRequest(router, http.MethodGet, "/")
// TEST
assert.Equal(t, http.StatusInternalServerError, w.Code)
@ -246,7 +246,7 @@ func TestMiddlewareWrite(t *testing.T) {
})
})
w := PerformRequest(router, "GET", "/")
w := PerformRequest(router, http.MethodGet, "/")
assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Equal(t, strings.Replace("hola\n<map><foo>bar</foo></map>{\"foo\":\"bar\"}{\"foo\":\"bar\"}event:test\ndata:message\n\n", " ", "", -1), strings.Replace(w.Body.String(), " ", "", -1))

View File

@ -5,7 +5,6 @@
package gin
import (
"fmt"
"net"
"net/http"
"os"
@ -26,14 +25,14 @@ func TestPanicClean(t *testing.T) {
panic("Oupps, Houston, we have a problem")
})
// RUN
w := PerformRequest(router, "GET", "/recovery",
w := PerformRequest(router, http.MethodGet, "/recovery",
header{
Key: "Host",
Value: "www.google.com",
},
header{
Key: "Authorization",
Value: fmt.Sprintf("Bearer %s", password),
Value: "Bearer " + password,
},
header{
Key: "Content-Type",
@ -56,7 +55,7 @@ func TestPanicInHandler(t *testing.T) {
panic("Oupps, Houston, we have a problem")
})
// RUN
w := PerformRequest(router, "GET", "/recovery")
w := PerformRequest(router, http.MethodGet, "/recovery")
// TEST
assert.Equal(t, http.StatusInternalServerError, w.Code)
assert.Contains(t, buffer.String(), "panic recovered")
@ -67,7 +66,7 @@ func TestPanicInHandler(t *testing.T) {
// Debug mode prints the request
SetMode(DebugMode)
// RUN
w = PerformRequest(router, "GET", "/recovery")
w = PerformRequest(router, http.MethodGet, "/recovery")
// TEST
assert.Equal(t, http.StatusInternalServerError, w.Code)
assert.Contains(t, buffer.String(), "GET /recovery")
@ -84,7 +83,7 @@ func TestPanicWithAbort(t *testing.T) {
panic("Oupps, Houston, we have a problem")
})
// RUN
w := PerformRequest(router, "GET", "/recovery")
w := PerformRequest(router, http.MethodGet, "/recovery")
// TEST
assert.Equal(t, http.StatusBadRequest, w.Code)
}
@ -135,7 +134,7 @@ func TestPanicWithBrokenPipe(t *testing.T) {
panic(e)
})
// RUN
w := PerformRequest(router, "GET", "/recovery")
w := PerformRequest(router, http.MethodGet, "/recovery")
// TEST
assert.Equal(t, expectCode, w.Code)
assert.Contains(t, strings.ToLower(buf.String()), expectMsg)
@ -156,7 +155,7 @@ func TestCustomRecoveryWithWriter(t *testing.T) {
panic("Oupps, Houston, we have a problem")
})
// RUN
w := PerformRequest(router, "GET", "/recovery")
w := PerformRequest(router, http.MethodGet, "/recovery")
// TEST
assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Contains(t, buffer.String(), "panic recovered")
@ -167,7 +166,7 @@ func TestCustomRecoveryWithWriter(t *testing.T) {
// Debug mode prints the request
SetMode(DebugMode)
// RUN
w = PerformRequest(router, "GET", "/recovery")
w = PerformRequest(router, http.MethodGet, "/recovery")
// TEST
assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Contains(t, buffer.String(), "GET /recovery")
@ -191,7 +190,7 @@ func TestCustomRecovery(t *testing.T) {
panic("Oupps, Houston, we have a problem")
})
// RUN
w := PerformRequest(router, "GET", "/recovery")
w := PerformRequest(router, http.MethodGet, "/recovery")
// TEST
assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Contains(t, buffer.String(), "panic recovered")
@ -202,7 +201,7 @@ func TestCustomRecovery(t *testing.T) {
// Debug mode prints the request
SetMode(DebugMode)
// RUN
w = PerformRequest(router, "GET", "/recovery")
w = PerformRequest(router, http.MethodGet, "/recovery")
// TEST
assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Contains(t, buffer.String(), "GET /recovery")
@ -226,7 +225,7 @@ func TestRecoveryWithWriterWithCustomRecovery(t *testing.T) {
panic("Oupps, Houston, we have a problem")
})
// RUN
w := PerformRequest(router, "GET", "/recovery")
w := PerformRequest(router, http.MethodGet, "/recovery")
// TEST
assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Contains(t, buffer.String(), "panic recovered")
@ -237,7 +236,7 @@ func TestRecoveryWithWriterWithCustomRecovery(t *testing.T) {
// Debug mode prints the request
SetMode(DebugMode)
// RUN
w = PerformRequest(router, "GET", "/recovery")
w = PerformRequest(router, http.MethodGet, "/recovery")
// TEST
assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Contains(t, buffer.String(), "GET /recovery")

View File

@ -369,7 +369,7 @@ func TestRenderXML(t *testing.T) {
}
func TestRenderRedirect(t *testing.T) {
req, err := http.NewRequest("GET", "/test-redirect", nil)
req, err := http.NewRequest(http.MethodGet, "/test-redirect", nil)
require.NoError(t, err)
data1 := Redirect{

View File

@ -523,8 +523,8 @@ func TestRouteNotAllowedEnabled3(t *testing.T) {
w := PerformRequest(router, http.MethodPut, "/path")
assert.Equal(t, http.StatusMethodNotAllowed, w.Code)
allowed := w.Header().Get("Allow")
assert.Contains(t, allowed, "GET")
assert.Contains(t, allowed, "POST")
assert.Contains(t, allowed, http.MethodGet)
assert.Contains(t, allowed, http.MethodPost)
}
func TestRouteNotAllowedDisabled(t *testing.T) {
@ -557,10 +557,10 @@ func TestRouterNotFoundWithRemoveExtraSlash(t *testing.T) {
{"/nope", http.StatusNotFound, ""}, // NotFound
}
for _, tr := range testRoutes {
w := PerformRequest(router, "GET", tr.route)
w := PerformRequest(router, http.MethodGet, tr.route)
assert.Equal(t, tr.code, w.Code)
if w.Code != http.StatusNotFound {
assert.Equal(t, tr.location, fmt.Sprint(w.Header().Get("Location")))
assert.Equal(t, tr.location, w.Header().Get("Location"))
}
}
}
@ -590,7 +590,7 @@ func TestRouterNotFound(t *testing.T) {
w := PerformRequest(router, http.MethodGet, tr.route)
assert.Equal(t, tr.code, w.Code)
if w.Code != http.StatusNotFound {
assert.Equal(t, tr.location, fmt.Sprint(w.Header().Get("Location")))
assert.Equal(t, tr.location, w.Header().Get("Location"))
}
}
@ -786,6 +786,6 @@ func TestEngineHandleMethodNotAllowedCornerCase(t *testing.T) {
v1.GET("/orgs/:id", handlerTest1)
v1.DELETE("/orgs/:id", handlerTest1)
w := PerformRequest(r, "GET", "/base/v1/user/groups")
w := PerformRequest(r, http.MethodGet, "/base/v1/user/groups")
assert.Equal(t, http.StatusNotFound, w.Code)
}

View File

@ -29,7 +29,7 @@ type testStruct struct {
}
func (t *testStruct) ServeHTTP(w http.ResponseWriter, req *http.Request) {
assert.Equal(t.T, "POST", req.Method)
assert.Equal(t.T, http.MethodPost, req.Method)
assert.Equal(t.T, "/path", req.URL.Path)
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprint(w, "hello")
@ -39,17 +39,17 @@ func TestWrap(t *testing.T) {
router := New()
router.POST("/path", WrapH(&testStruct{t}))
router.GET("/path2", WrapF(func(w http.ResponseWriter, req *http.Request) {
assert.Equal(t, "GET", req.Method)
assert.Equal(t, http.MethodGet, req.Method)
assert.Equal(t, "/path2", req.URL.Path)
w.WriteHeader(http.StatusBadRequest)
fmt.Fprint(w, "hola!")
}))
w := PerformRequest(router, "POST", "/path")
w := PerformRequest(router, http.MethodPost, "/path")
assert.Equal(t, http.StatusInternalServerError, w.Code)
assert.Equal(t, "hello", w.Body.String())
w = PerformRequest(router, "GET", "/path2")
w = PerformRequest(router, http.MethodGet, "/path2")
assert.Equal(t, http.StatusBadRequest, w.Code)
assert.Equal(t, "hola!", w.Body.String())
}
@ -119,13 +119,13 @@ func TestBindMiddleware(t *testing.T) {
called = true
value = c.MustGet(BindKey).(*bindTestStruct)
})
PerformRequest(router, "GET", "/?foo=hola&bar=10")
PerformRequest(router, http.MethodGet, "/?foo=hola&bar=10")
assert.True(t, called)
assert.Equal(t, "hola", value.Foo)
assert.Equal(t, 10, value.Bar)
called = false
PerformRequest(router, "GET", "/?foo=hola&bar=1")
PerformRequest(router, http.MethodGet, "/?foo=hola&bar=1")
assert.False(t, called)
assert.Panics(t, func() {