Add Jsonp Support to Context (#1333)

This commit is contained in:
senhtry
2018-04-26 11:52:19 +08:00
committed by Bo-Yi Wu
parent 41f951e0cd
commit 8c24018290
6 changed files with 114 additions and 0 deletions

32
render/json.go Normal file → Executable file
View File

@ -6,6 +6,7 @@ package render
import (
"bytes"
"html/template"
"net/http"
"github.com/gin-gonic/gin/json"
@ -24,9 +25,15 @@ type SecureJSON struct {
Data interface{}
}
type JsonpJSON struct {
Callback string
Data interface{}
}
type SecureJSONPrefix string
var jsonContentType = []string{"application/json; charset=utf-8"}
var jsonpContentType = []string{"application/javascript; charset=utf-8"}
func (r JSON) Render(w http.ResponseWriter) (err error) {
if err = WriteJSON(w, r.Data); err != nil {
@ -80,3 +87,28 @@ func (r SecureJSON) Render(w http.ResponseWriter) error {
func (r SecureJSON) WriteContentType(w http.ResponseWriter) {
writeContentType(w, jsonContentType)
}
func (r JsonpJSON) Render(w http.ResponseWriter) (err error) {
r.WriteContentType(w)
ret, err := json.Marshal(r.Data)
if err != nil {
return err
}
if r.Callback == "" {
w.Write(ret)
return nil
}
callback := template.JSEscapeString(r.Callback)
w.Write([]byte(callback))
w.Write([]byte("("))
w.Write(ret)
w.Write([]byte(")"))
return nil
}
func (r JsonpJSON) WriteContentType(w http.ResponseWriter) {
writeContentType(w, jsonpContentType)
}

1
render/render.go Normal file → Executable file
View File

@ -15,6 +15,7 @@ var (
_ Render = JSON{}
_ Render = IndentedJSON{}
_ Render = SecureJSON{}
_ Render = JsonpJSON{}
_ Render = XML{}
_ Render = String{}
_ Render = Redirect{}

37
render/render_test.go Normal file → Executable file
View File

@ -128,6 +128,43 @@ func TestRenderSecureJSONFail(t *testing.T) {
assert.Error(t, err)
}
func TestRenderJsonpJSON(t *testing.T) {
w1 := httptest.NewRecorder()
data := map[string]interface{}{
"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)
assert.NoError(t, err1)
assert.Equal(t, "x({\"foo\":\"bar\"})", w1.Body.String())
assert.Equal(t, "application/javascript; charset=utf-8", w1.Header().Get("Content-Type"))
w2 := httptest.NewRecorder()
datas := []map[string]interface{}{{
"foo": "bar",
}, {
"bar": "foo",
}}
err2 := (JsonpJSON{"x", datas}).Render(w2)
assert.NoError(t, err2)
assert.Equal(t, "x([{\"foo\":\"bar\"},{\"bar\":\"foo\"}])", w2.Body.String())
assert.Equal(t, "application/javascript; charset=utf-8", w2.Header().Get("Content-Type"))
}
func TestRenderJsonpJSONFail(t *testing.T) {
w := httptest.NewRecorder()
data := make(chan int)
// json: unsupported type: chan int
err := (JsonpJSON{"x", data}).Render(w)
assert.Error(t, err)
}
type xmlmap map[string]interface{}
// Allows type H to be used with xml.Marshal