2022-05-28 05:42:28 +03:00
|
|
|
// Copyright 2014 Manu Martinez-Almeida. All rights reserved.
|
2015-04-09 13:15:02 +03:00
|
|
|
// Use of this source code is governed by a MIT style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package render
|
|
|
|
|
|
|
|
import (
|
2015-05-07 13:44:52 +03:00
|
|
|
"encoding/xml"
|
2018-01-26 06:46:11 +03:00
|
|
|
"errors"
|
2015-04-09 13:15:02 +03:00
|
|
|
"html/template"
|
2022-12-22 18:18:47 +03:00
|
|
|
"net"
|
2018-01-26 06:46:11 +03:00
|
|
|
"net/http"
|
2015-04-09 13:15:02 +03:00
|
|
|
"net/http/httptest"
|
2018-05-12 06:00:42 +03:00
|
|
|
"strconv"
|
|
|
|
"strings"
|
2015-04-09 13:15:02 +03:00
|
|
|
"testing"
|
|
|
|
|
2023-05-10 12:19:26 +03:00
|
|
|
"github.com/gin-gonic/gin/internal/json"
|
2021-09-21 10:22:21 +03:00
|
|
|
testdata "github.com/gin-gonic/gin/testdata/protoexample"
|
2015-04-09 13:15:02 +03:00
|
|
|
"github.com/stretchr/testify/assert"
|
2024-07-14 15:33:08 +03:00
|
|
|
"github.com/stretchr/testify/require"
|
2021-08-19 10:46:31 +03:00
|
|
|
"google.golang.org/protobuf/proto"
|
2015-04-09 13:15:02 +03:00
|
|
|
)
|
|
|
|
|
2015-05-09 04:35:31 +03:00
|
|
|
// TODO unit tests
|
|
|
|
// test errors
|
|
|
|
|
2015-04-09 13:15:02 +03:00
|
|
|
func TestRenderJSON(t *testing.T) {
|
|
|
|
w := httptest.NewRecorder()
|
2022-03-21 04:43:17 +03:00
|
|
|
data := map[string]any{
|
2018-08-20 10:15:31 +03:00
|
|
|
"foo": "bar",
|
|
|
|
"html": "<b>",
|
2015-05-07 13:44:52 +03:00
|
|
|
}
|
|
|
|
|
2018-01-26 06:46:11 +03:00
|
|
|
(JSON{data}).WriteContentType(w)
|
|
|
|
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
|
|
|
|
|
2015-06-04 06:25:21 +03:00
|
|
|
err := (JSON{data}).Render(w)
|
2015-04-09 13:15:02 +03:00
|
|
|
|
2024-07-14 15:33:08 +03:00
|
|
|
require.NoError(t, err)
|
2020-02-21 12:15:17 +03:00
|
|
|
assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}", w.Body.String())
|
2016-12-11 05:14:20 +03:00
|
|
|
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
|
2015-04-09 13:15:02 +03:00
|
|
|
}
|
|
|
|
|
2023-02-12 05:01:33 +03:00
|
|
|
func TestRenderJSONError(t *testing.T) {
|
2018-01-26 06:46:11 +03:00
|
|
|
w := httptest.NewRecorder()
|
|
|
|
data := make(chan int)
|
|
|
|
|
|
|
|
// json: unsupported type: chan int
|
2024-07-14 15:33:08 +03:00
|
|
|
require.Error(t, (JSON{data}).Render(w))
|
2018-01-26 06:46:11 +03:00
|
|
|
}
|
|
|
|
|
2015-04-09 13:15:02 +03:00
|
|
|
func TestRenderIndentedJSON(t *testing.T) {
|
|
|
|
w := httptest.NewRecorder()
|
2022-03-21 04:43:17 +03:00
|
|
|
data := map[string]any{
|
2015-04-09 13:15:02 +03:00
|
|
|
"foo": "bar",
|
|
|
|
"bar": "foo",
|
2015-05-18 16:45:24 +03:00
|
|
|
}
|
|
|
|
|
2015-06-04 06:25:21 +03:00
|
|
|
err := (IndentedJSON{data}).Render(w)
|
2015-04-09 13:15:02 +03:00
|
|
|
|
2024-07-14 15:33:08 +03:00
|
|
|
require.NoError(t, err)
|
2018-04-20 05:27:44 +03:00
|
|
|
assert.Equal(t, "{\n \"bar\": \"foo\",\n \"foo\": \"bar\"\n}", w.Body.String())
|
|
|
|
assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
|
2015-04-09 13:15:02 +03:00
|
|
|
}
|
|
|
|
|
2018-01-26 06:46:11 +03:00
|
|
|
func TestRenderIndentedJSONPanics(t *testing.T) {
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
data := make(chan int)
|
|
|
|
|
|
|
|
// json: unsupported type: chan int
|
|
|
|
err := (IndentedJSON{data}).Render(w)
|
2024-07-14 15:33:08 +03:00
|
|
|
require.Error(t, err)
|
2018-01-26 06:46:11 +03:00
|
|
|
}
|
|
|
|
|
2017-07-07 20:21:30 +03:00
|
|
|
func TestRenderSecureJSON(t *testing.T) {
|
|
|
|
w1 := httptest.NewRecorder()
|
2022-03-21 04:43:17 +03:00
|
|
|
data := map[string]any{
|
2017-07-07 20:21:30 +03:00
|
|
|
"foo": "bar",
|
|
|
|
}
|
|
|
|
|
2018-01-26 06:46:11 +03:00
|
|
|
(SecureJSON{"while(1);", data}).WriteContentType(w1)
|
|
|
|
assert.Equal(t, "application/json; charset=utf-8", w1.Header().Get("Content-Type"))
|
|
|
|
|
2017-07-07 20:21:30 +03:00
|
|
|
err1 := (SecureJSON{"while(1);", data}).Render(w1)
|
|
|
|
|
2024-07-14 15:33:08 +03:00
|
|
|
require.NoError(t, err1)
|
2017-07-07 20:21:30 +03:00
|
|
|
assert.Equal(t, "{\"foo\":\"bar\"}", w1.Body.String())
|
|
|
|
assert.Equal(t, "application/json; charset=utf-8", w1.Header().Get("Content-Type"))
|
|
|
|
|
|
|
|
w2 := httptest.NewRecorder()
|
2022-03-21 04:43:17 +03:00
|
|
|
datas := []map[string]any{{
|
2017-07-07 20:21:30 +03:00
|
|
|
"foo": "bar",
|
|
|
|
}, {
|
|
|
|
"bar": "foo",
|
|
|
|
}}
|
|
|
|
|
|
|
|
err2 := (SecureJSON{"while(1);", datas}).Render(w2)
|
2024-07-14 15:33:08 +03:00
|
|
|
require.NoError(t, err2)
|
2017-07-07 20:21:30 +03:00
|
|
|
assert.Equal(t, "while(1);[{\"foo\":\"bar\"},{\"bar\":\"foo\"}]", w2.Body.String())
|
|
|
|
assert.Equal(t, "application/json; charset=utf-8", w2.Header().Get("Content-Type"))
|
|
|
|
}
|
|
|
|
|
2018-01-26 06:46:11 +03:00
|
|
|
func TestRenderSecureJSONFail(t *testing.T) {
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
data := make(chan int)
|
|
|
|
|
|
|
|
// json: unsupported type: chan int
|
|
|
|
err := (SecureJSON{"while(1);", data}).Render(w)
|
2024-07-14 15:33:08 +03:00
|
|
|
require.Error(t, err)
|
2018-01-26 06:46:11 +03:00
|
|
|
}
|
|
|
|
|
2018-04-26 06:52:19 +03:00
|
|
|
func TestRenderJsonpJSON(t *testing.T) {
|
|
|
|
w1 := httptest.NewRecorder()
|
2022-03-21 04:43:17 +03:00
|
|
|
data := map[string]any{
|
2018-04-26 06:52:19 +03:00
|
|
|
"foo": "bar",
|
|
|
|
}
|
|
|
|
|
|
|
|
(JsonpJSON{"x", data}).WriteContentType(w1)
|
|
|
|
assert.Equal(t, "application/javascript; charset=utf-8", w1.Header().Get("Content-Type"))
|
|
|
|
|
|
|
|
err1 := (JsonpJSON{"x", data}).Render(w1)
|
|
|
|
|
2024-07-14 15:33:08 +03:00
|
|
|
require.NoError(t, err1)
|
2019-09-02 15:18:08 +03:00
|
|
|
assert.Equal(t, "x({\"foo\":\"bar\"});", w1.Body.String())
|
2018-04-26 06:52:19 +03:00
|
|
|
assert.Equal(t, "application/javascript; charset=utf-8", w1.Header().Get("Content-Type"))
|
|
|
|
|
|
|
|
w2 := httptest.NewRecorder()
|
2022-03-21 04:43:17 +03:00
|
|
|
datas := []map[string]any{{
|
2018-04-26 06:52:19 +03:00
|
|
|
"foo": "bar",
|
|
|
|
}, {
|
|
|
|
"bar": "foo",
|
|
|
|
}}
|
|
|
|
|
|
|
|
err2 := (JsonpJSON{"x", datas}).Render(w2)
|
2024-07-14 15:33:08 +03:00
|
|
|
require.NoError(t, err2)
|
2019-09-02 15:18:08 +03:00
|
|
|
assert.Equal(t, "x([{\"foo\":\"bar\"},{\"bar\":\"foo\"}]);", w2.Body.String())
|
2018-04-26 06:52:19 +03:00
|
|
|
assert.Equal(t, "application/javascript; charset=utf-8", w2.Header().Get("Content-Type"))
|
|
|
|
}
|
|
|
|
|
2023-05-10 12:19:26 +03:00
|
|
|
type errorWriter struct {
|
|
|
|
bufString string
|
|
|
|
*httptest.ResponseRecorder
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ http.ResponseWriter = (*errorWriter)(nil)
|
|
|
|
|
|
|
|
func (w *errorWriter) Write(buf []byte) (int, error) {
|
|
|
|
if string(buf) == w.bufString {
|
|
|
|
return 0, errors.New(`write "` + w.bufString + `" error`)
|
|
|
|
}
|
|
|
|
return w.ResponseRecorder.Write(buf)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRenderJsonpJSONError(t *testing.T) {
|
|
|
|
ew := &errorWriter{
|
|
|
|
ResponseRecorder: httptest.NewRecorder(),
|
|
|
|
}
|
|
|
|
|
|
|
|
jsonpJSON := JsonpJSON{
|
|
|
|
Callback: "foo",
|
|
|
|
Data: map[string]string{
|
|
|
|
"foo": "bar",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
cb := template.JSEscapeString(jsonpJSON.Callback)
|
|
|
|
ew.bufString = cb
|
|
|
|
err := jsonpJSON.Render(ew) // error was returned while writing callback
|
|
|
|
assert.Equal(t, `write "`+cb+`" error`, err.Error())
|
|
|
|
|
|
|
|
ew.bufString = `(`
|
|
|
|
err = jsonpJSON.Render(ew)
|
|
|
|
assert.Equal(t, `write "`+`(`+`" error`, err.Error())
|
|
|
|
|
|
|
|
data, _ := json.Marshal(jsonpJSON.Data) // error was returned while writing data
|
|
|
|
ew.bufString = string(data)
|
|
|
|
err = jsonpJSON.Render(ew)
|
|
|
|
assert.Equal(t, `write "`+string(data)+`" error`, err.Error())
|
|
|
|
|
|
|
|
ew.bufString = `);`
|
|
|
|
err = jsonpJSON.Render(ew)
|
|
|
|
assert.Equal(t, `write "`+`);`+`" error`, err.Error())
|
|
|
|
}
|
|
|
|
|
2018-08-12 17:02:37 +03:00
|
|
|
func TestRenderJsonpJSONError2(t *testing.T) {
|
|
|
|
w := httptest.NewRecorder()
|
2022-03-21 04:43:17 +03:00
|
|
|
data := map[string]any{
|
2018-08-12 17:02:37 +03:00
|
|
|
"foo": "bar",
|
|
|
|
}
|
|
|
|
(JsonpJSON{"", data}).WriteContentType(w)
|
|
|
|
assert.Equal(t, "application/javascript; charset=utf-8", w.Header().Get("Content-Type"))
|
|
|
|
|
|
|
|
e := (JsonpJSON{"", data}).Render(w)
|
2024-07-14 15:33:08 +03:00
|
|
|
require.NoError(t, e)
|
2018-08-12 17:02:37 +03:00
|
|
|
|
|
|
|
assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
|
|
|
|
assert.Equal(t, "application/javascript; charset=utf-8", w.Header().Get("Content-Type"))
|
|
|
|
}
|
|
|
|
|
2018-04-26 06:52:19 +03:00
|
|
|
func TestRenderJsonpJSONFail(t *testing.T) {
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
data := make(chan int)
|
|
|
|
|
|
|
|
// json: unsupported type: chan int
|
|
|
|
err := (JsonpJSON{"x", data}).Render(w)
|
2024-07-14 15:33:08 +03:00
|
|
|
require.Error(t, err)
|
2018-04-26 06:52:19 +03:00
|
|
|
}
|
|
|
|
|
2018-07-03 12:17:08 +03:00
|
|
|
func TestRenderAsciiJSON(t *testing.T) {
|
|
|
|
w1 := httptest.NewRecorder()
|
2022-03-21 04:43:17 +03:00
|
|
|
data1 := map[string]any{
|
2018-07-03 12:17:08 +03:00
|
|
|
"lang": "GO语言",
|
|
|
|
"tag": "<br>",
|
|
|
|
}
|
|
|
|
|
|
|
|
err := (AsciiJSON{data1}).Render(w1)
|
|
|
|
|
2024-07-14 15:33:08 +03:00
|
|
|
require.NoError(t, err)
|
2018-07-03 12:17:08 +03:00
|
|
|
assert.Equal(t, "{\"lang\":\"GO\\u8bed\\u8a00\",\"tag\":\"\\u003cbr\\u003e\"}", w1.Body.String())
|
|
|
|
assert.Equal(t, "application/json", w1.Header().Get("Content-Type"))
|
|
|
|
|
|
|
|
w2 := httptest.NewRecorder()
|
2022-10-16 04:49:24 +03:00
|
|
|
data2 := 3.1415926
|
2018-07-03 12:17:08 +03:00
|
|
|
|
|
|
|
err = (AsciiJSON{data2}).Render(w2)
|
2024-07-14 15:33:08 +03:00
|
|
|
require.NoError(t, err)
|
2018-07-03 12:17:08 +03:00
|
|
|
assert.Equal(t, "3.1415926", w2.Body.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRenderAsciiJSONFail(t *testing.T) {
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
data := make(chan int)
|
|
|
|
|
|
|
|
// json: unsupported type: chan int
|
2024-07-14 15:33:08 +03:00
|
|
|
require.Error(t, (AsciiJSON{data}).Render(w))
|
2018-07-03 12:17:08 +03:00
|
|
|
}
|
|
|
|
|
2019-05-07 13:32:32 +03:00
|
|
|
func TestRenderPureJSON(t *testing.T) {
|
|
|
|
w := httptest.NewRecorder()
|
2022-03-21 04:43:17 +03:00
|
|
|
data := map[string]any{
|
2019-05-07 13:32:32 +03:00
|
|
|
"foo": "bar",
|
|
|
|
"html": "<b>",
|
|
|
|
}
|
|
|
|
err := (PureJSON{data}).Render(w)
|
|