|
|
|
|
@ -28,6 +28,7 @@ import (
|
|
|
|
|
|
|
|
|
|
"github.com/gin-contrib/sse"
|
|
|
|
|
"github.com/gin-gonic/gin/binding"
|
|
|
|
|
"github.com/gin-gonic/gin/internal/json"
|
|
|
|
|
testdata "github.com/gin-gonic/gin/testdata/protoexample"
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
@ -173,6 +174,9 @@ func TestSaveUploadedFileWithPermission(t *testing.T) {
|
|
|
|
|
assert.Equal(t, "permission_test", f.Filename)
|
|
|
|
|
var mode fs.FileMode = 0o755
|
|
|
|
|
require.NoError(t, c.SaveUploadedFile(f, "permission_test", mode))
|
|
|
|
|
t.Cleanup(func() {
|
|
|
|
|
assert.NoError(t, os.Remove("permission_test"))
|
|
|
|
|
})
|
|
|
|
|
info, err := os.Stat(filepath.Dir("permission_test"))
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Equal(t, info.Mode().Perm(), mode)
|
|
|
|
|
@ -671,7 +675,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")
|
|
|
|
|
body := strings.NewReader("foo=bar&page=11&both=&foo=second")
|
|
|
|
|
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)
|
|
|
|
|
@ -946,7 +950,7 @@ func TestContextRenderJSONPWithoutCallback(t *testing.T) {
|
|
|
|
|
c.JSONP(http.StatusCreated, H{"foo": "bar"})
|
|
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusCreated, w.Code)
|
|
|
|
|
assert.JSONEq(t, "{\"foo\":\"bar\"}", w.Body.String())
|
|
|
|
|
assert.JSONEq(t, `{"foo":"bar"}`, w.Body.String())
|
|
|
|
|
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -972,7 +976,7 @@ func TestContextRenderAPIJSON(t *testing.T) {
|
|
|
|
|
c.JSON(http.StatusCreated, H{"foo": "bar"})
|
|
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusCreated, w.Code)
|
|
|
|
|
assert.JSONEq(t, "{\"foo\":\"bar\"}", w.Body.String())
|
|
|
|
|
assert.JSONEq(t, `{"foo":"bar"}`, w.Body.String())
|
|
|
|
|
assert.Equal(t, "application/vnd.api+json", w.Header().Get("Content-Type"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1432,7 +1436,7 @@ func TestContextNegotiationWithJSON(t *testing.T) {
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
assert.Equal(t, http.StatusOK, w.Code)
|
|
|
|
|
assert.JSONEq(t, "{\"foo\":\"bar\"}", w.Body.String())
|
|
|
|
|
assert.JSONEq(t, `{"foo":"bar"}`, w.Body.String())
|
|
|
|
|
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1848,9 +1852,41 @@ func TestContextContentType(t *testing.T) {
|
|
|
|
|
assert.Equal(t, "application/json", c.ContentType())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestContextBindRequestTooLarge(t *testing.T) {
|
|
|
|
|
// When using sonic or go-json as JSON encoder, they do not propagate the http.MaxBytesError error
|
|
|
|
|
// The response will fail with a generic 400 instead of 413
|
|
|
|
|
// https://github.com/goccy/go-json/issues/485
|
|
|
|
|
// https://github.com/bytedance/sonic/issues/800
|
|
|
|
|
var expectedCode int
|
|
|
|
|
switch json.Package {
|
|
|
|
|
case "github.com/goccy/go-json", "github.com/bytedance/sonic":
|
|
|
|
|
expectedCode = http.StatusBadRequest
|
|
|
|
|
default:
|
|
|
|
|
expectedCode = http.StatusRequestEntityTooLarge
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
c, _ := CreateTestContext(w)
|
|
|
|
|
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", strings.NewReader(`{"foo":"bar", "bar":"foo"}`))
|
|
|
|
|
c.Request.Body = http.MaxBytesReader(c.Writer, c.Request.Body, 10)
|
|
|
|
|
|
|
|
|
|
var obj struct {
|
|
|
|
|
Foo string `json:"foo"`
|
|
|
|
|
Bar string `json:"bar"`
|
|
|
|
|
}
|
|
|
|
|
require.Error(t, c.BindJSON(&obj))
|
|
|
|
|
c.Writer.WriteHeaderNow()
|
|
|
|
|
|
|
|
|
|
assert.Empty(t, obj.Bar)
|
|
|
|
|
assert.Empty(t, obj.Foo)
|
|
|
|
|
assert.Equal(t, expectedCode, w.Code)
|
|
|
|
|
assert.True(t, c.IsAborted())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestContextAutoBindJSON(t *testing.T) {
|
|
|
|
|
c, _ := CreateTestContext(httptest.NewRecorder())
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", strings.NewReader(`{"foo":"bar", "bar":"foo"}`))
|
|
|
|
|
c.Request.Header.Add("Content-Type", MIMEJSON)
|
|
|
|
|
|
|
|
|
|
var obj struct {
|
|
|
|
|
@ -1867,7 +1903,7 @@ func TestContextBindWithJSON(t *testing.T) {
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
c, _ := CreateTestContext(w)
|
|
|
|
|
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", strings.NewReader(`{"foo":"bar", "bar":"foo"}`))
|
|
|
|
|
c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
|
|
|
|
|
|
|
|
|
|
var obj struct {
|
|
|
|
|
@ -1884,7 +1920,7 @@ func TestContextBindWithXML(t *testing.T) {
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
c, _ := CreateTestContext(w)
|
|
|
|
|
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", strings.NewReader(`<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
<root>
|
|
|
|
|
<foo>FOO</foo>
|
|
|
|
|
<bar>BAR</bar>
|
|
|
|
|
@ -1951,7 +1987,7 @@ func TestContextBindWithQuery(t *testing.T) {
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
c, _ := CreateTestContext(w)
|
|
|
|
|
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/?foo=bar&bar=foo", bytes.NewBufferString("foo=unused"))
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/?foo=bar&bar=foo", strings.NewReader("foo=unused"))
|
|
|
|
|
|
|
|
|
|
var obj struct {
|
|
|
|
|
Foo string `form:"foo"`
|
|
|
|
|
@ -1967,7 +2003,7 @@ func TestContextBindWithYAML(t *testing.T) {
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
c, _ := CreateTestContext(w)
|
|
|
|
|
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("foo: bar\nbar: foo"))
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", strings.NewReader("foo: bar\nbar: foo"))
|
|
|
|
|
c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
|
|
|
|
|
|
|
|
|
|
var obj struct {
|
|
|
|
|
@ -1984,7 +2020,7 @@ func TestContextBindWithTOML(t *testing.T) {
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
c, _ := CreateTestContext(w)
|
|
|
|
|
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("foo = 'bar'\nbar = 'foo'"))
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", strings.NewReader("foo = 'bar'\nbar = 'foo'"))
|
|
|
|
|
c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
|
|
|
|
|
|
|
|
|
|
var obj struct {
|
|
|
|
|
@ -2001,7 +2037,7 @@ func TestContextBadAutoBind(t *testing.T) {
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
c, _ := CreateTestContext(w)
|
|
|
|
|
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "http://example.com", bytes.NewBufferString("\"foo\":\"bar\", \"bar\":\"foo\"}"))
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "http://example.com", strings.NewReader("\"foo\":\"bar\", \"bar\":\"foo\"}"))
|
|
|
|
|
c.Request.Header.Add("Content-Type", MIMEJSON)
|
|
|
|
|
var obj struct {
|
|
|
|
|
Foo string `json:"foo"`
|
|
|
|
|
@ -2020,7 +2056,7 @@ func TestContextBadAutoBind(t *testing.T) {
|
|
|
|
|
|
|
|
|
|
func TestContextAutoShouldBindJSON(t *testing.T) {
|
|
|
|
|
c, _ := CreateTestContext(httptest.NewRecorder())
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", strings.NewReader(`{"foo":"bar", "bar":"foo"}`))
|
|
|
|
|
c.Request.Header.Add("Content-Type", MIMEJSON)
|
|
|
|
|
|
|
|
|
|
var obj struct {
|
|
|
|
|
@ -2037,7 +2073,7 @@ func TestContextShouldBindWithJSON(t *testing.T) {
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
c, _ := CreateTestContext(w)
|
|
|
|
|
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", strings.NewReader(`{"foo":"bar", "bar":"foo"}`))
|
|
|
|
|
c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
|
|
|
|
|
|
|
|
|
|
var obj struct {
|
|
|
|
|
@ -2054,7 +2090,7 @@ func TestContextShouldBindWithXML(t *testing.T) {
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
c, _ := CreateTestContext(w)
|
|
|
|
|
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", strings.NewReader(`<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
<root>
|
|
|
|
|
<foo>FOO</foo>
|
|
|
|
|
<bar>BAR</bar>
|
|
|
|
|
@ -2121,7 +2157,7 @@ func TestContextShouldBindWithQuery(t *testing.T) {
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
c, _ := CreateTestContext(w)
|
|
|
|
|
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/?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", strings.NewReader("foo=unused"))
|
|
|
|
|
|
|
|
|
|
var obj struct {
|
|
|
|
|
Foo string `form:"foo"`
|
|
|
|
|
@ -2141,7 +2177,7 @@ func TestContextShouldBindWithYAML(t *testing.T) {
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
c, _ := CreateTestContext(w)
|
|
|
|
|
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("foo: bar\nbar: foo"))
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", strings.NewReader("foo: bar\nbar: foo"))
|
|
|
|
|
c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
|
|
|
|
|
|
|
|
|
|
var obj struct {
|
|
|
|
|
@ -2158,7 +2194,7 @@ func TestContextShouldBindWithTOML(t *testing.T) {
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
c, _ := CreateTestContext(w)
|
|
|
|
|
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("foo='bar'\nbar= 'foo'"))
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", strings.NewReader("foo='bar'\nbar= 'foo'"))
|
|
|
|
|
c.Request.Header.Add("Content-Type", MIMETOML) // set fake content-type
|
|
|
|
|
|
|
|
|
|
var obj struct {
|
|
|
|
|
@ -2175,7 +2211,7 @@ func TestContextBadAutoShouldBind(t *testing.T) {
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
c, _ := CreateTestContext(w)
|
|
|
|
|
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "http://example.com", bytes.NewBufferString("\"foo\":\"bar\", \"bar\":\"foo\"}"))
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "http://example.com", strings.NewReader(`"foo":"bar", "bar":"foo"}`))
|
|
|
|
|
c.Request.Header.Add("Content-Type", MIMEJSON)
|
|
|
|
|
var obj struct {
|
|
|
|
|
Foo string `json:"foo"`
|
|
|
|
|
@ -2239,7 +2275,7 @@ func TestContextShouldBindBodyWith(t *testing.T) {
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
c, _ := CreateTestContext(w)
|
|
|
|
|
c.Request, _ = http.NewRequest(
|
|
|
|
|
http.MethodPost, "http://example.com", bytes.NewBufferString(tt.bodyA),
|
|
|
|
|
http.MethodPost, "http://example.com", strings.NewReader(tt.bodyA),
|
|
|
|
|
)
|
|
|
|
|
// When it binds to typeA and typeB, it finds the body is
|
|
|
|
|
// not typeB but typeA.
|
|
|
|
|
@ -2257,7 +2293,7 @@ func TestContextShouldBindBodyWith(t *testing.T) {
|
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
|
c, _ := CreateTestContext(w)
|
|
|
|
|
c.Request, _ = http.NewRequest(
|
|
|
|
|
http.MethodPost, "http://example.com", bytes.NewBufferString(tt.bodyB),
|
|
|
|
|
http.MethodPost, "http://example.com", strings.NewReader(tt.bodyB),
|
|
|
|
|
)
|
|
|
|
|
objA := typeA{}
|
|
|
|
|
require.Error(t, c.ShouldBindBodyWith(&objA, tt.bindingA))
|
|
|
|
|
@ -2603,7 +2639,7 @@ func TestContextShouldBindBodyWithPlain(t *testing.T) {
|
|
|
|
|
|
|
|
|
|
func TestContextGolangContext(t *testing.T) {
|
|
|
|
|
c, _ := CreateTestContext(httptest.NewRecorder())
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", strings.NewReader(`{"foo":"bar", "bar":"foo"}`))
|
|
|
|
|
require.NoError(t, c.Err())
|
|
|
|
|
assert.Nil(t, c.Done())
|
|
|
|
|
ti, ok := c.Deadline()
|
|
|
|
|
@ -2651,7 +2687,7 @@ func TestGetRequestHeaderValue(t *testing.T) {
|
|
|
|
|
|
|
|
|
|
func TestContextGetRawData(t *testing.T) {
|
|
|
|
|
c, _ := CreateTestContext(httptest.NewRecorder())
|
|
|
|
|
body := bytes.NewBufferString("Fetch binary post data")
|
|
|
|
|
body := strings.NewReader("Fetch binary post data")
|
|
|
|
|
c.Request, _ = http.NewRequest(http.MethodPost, "/", body)
|
|
|
|
|
c.Request.Header.Add("Content-Type", MIMEPOSTForm)
|
|
|
|
|
|
|
|
|
|
|