mirror of
https://github.com/gin-gonic/gin.git
synced 2026-01-11 00:56:57 +08:00
Add support for the new function in Render interface for writing content-type only
This commit is contained in:
parent
bcb044bbc3
commit
2f166fe9cc
30
context.go
30
context.go
@ -17,7 +17,7 @@ import (
|
|||||||
|
|
||||||
"github.com/gin-gonic/gin/binding"
|
"github.com/gin-gonic/gin/binding"
|
||||||
"github.com/gin-gonic/gin/render"
|
"github.com/gin-gonic/gin/render"
|
||||||
"github.com/manucorporat/sse"
|
"gopkg.in/gin-contrib/sse.v0"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Content-Type MIME of the most common data formats
|
// Content-Type MIME of the most common data formats
|
||||||
@ -404,6 +404,19 @@ func (c *Context) requestHeader(key string) string {
|
|||||||
/******** RESPONSE RENDERING ********/
|
/******** RESPONSE RENDERING ********/
|
||||||
/************************************/
|
/************************************/
|
||||||
|
|
||||||
|
// bodyAllowedForStatus is a copy of http.bodyAllowedForStatus non-exported function
|
||||||
|
func bodyAllowedForStatus(status int) bool {
|
||||||
|
switch {
|
||||||
|
case status >= 100 && status <= 199:
|
||||||
|
return false
|
||||||
|
case status == 204:
|
||||||
|
return false
|
||||||
|
case status == 304:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Context) Status(code int) {
|
func (c *Context) Status(code int) {
|
||||||
c.writermem.WriteHeader(code)
|
c.writermem.WriteHeader(code)
|
||||||
}
|
}
|
||||||
@ -453,6 +466,13 @@ func (c *Context) Cookie(name string) (string, error) {
|
|||||||
|
|
||||||
func (c *Context) Render(code int, r render.Render) {
|
func (c *Context) Render(code int, r render.Render) {
|
||||||
c.Status(code)
|
c.Status(code)
|
||||||
|
|
||||||
|
if !bodyAllowedForStatus(code) {
|
||||||
|
r.WriteContentType(c.Writer)
|
||||||
|
c.Writer.WriteHeaderNow()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err := r.Render(c.Writer); err != nil {
|
if err := r.Render(c.Writer); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -477,10 +497,7 @@ func (c *Context) IndentedJSON(code int, obj interface{}) {
|
|||||||
// JSON serializes the given struct as JSON into the response body.
|
// JSON serializes the given struct as JSON into the response body.
|
||||||
// It also sets the Content-Type as "application/json".
|
// It also sets the Content-Type as "application/json".
|
||||||
func (c *Context) JSON(code int, obj interface{}) {
|
func (c *Context) JSON(code int, obj interface{}) {
|
||||||
c.Status(code)
|
c.Render(code, render.JSON{Data: obj})
|
||||||
if err := render.WriteJSON(c.Writer, obj); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// XML serializes the given struct as XML into the response body.
|
// XML serializes the given struct as XML into the response body.
|
||||||
@ -496,8 +513,7 @@ func (c *Context) YAML(code int, obj interface{}) {
|
|||||||
|
|
||||||
// String writes the given string into the response body.
|
// String writes the given string into the response body.
|
||||||
func (c *Context) String(code int, format string, values ...interface{}) {
|
func (c *Context) String(code int, format string, values ...interface{}) {
|
||||||
c.Status(code)
|
c.Render(code, render.String{Format: format, Data: values})
|
||||||
render.WriteString(c.Writer, format, values)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Redirect returns a HTTP redirect to the specific location.
|
// Redirect returns a HTTP redirect to the specific location.
|
||||||
|
|||||||
102
context_test.go
102
context_test.go
@ -15,9 +15,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/manucorporat/sse"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
"gopkg.in/gin-contrib/sse.v0"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ context.Context = &Context{}
|
var _ context.Context = &Context{}
|
||||||
@ -394,6 +394,18 @@ func TestContextRenderJSON(t *testing.T) {
|
|||||||
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that no JSON is rendered if code is 204
|
||||||
|
func TestContextRenderNoContentJSON(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, _ := CreateTestContext(w)
|
||||||
|
|
||||||
|
c.JSON(204, H{"foo": "bar"})
|
||||||
|
|
||||||
|
assert.Equal(t, 204, w.Code)
|
||||||
|
assert.Equal(t, "", w.Body.String())
|
||||||
|
assert.Equal(t, "application/json; charset=utf-8", w.HeaderMap.Get("Content-Type"))
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that the response is serialized as JSON
|
// Tests that the response is serialized as JSON
|
||||||
// we change the content-type before
|
// we change the content-type before
|
||||||
func TestContextRenderAPIJSON(t *testing.T) {
|
func TestContextRenderAPIJSON(t *testing.T) {
|
||||||
@ -408,6 +420,19 @@ func TestContextRenderAPIJSON(t *testing.T) {
|
|||||||
assert.Equal(t, "application/vnd.api+json", w.HeaderMap.Get("Content-Type"))
|
assert.Equal(t, "application/vnd.api+json", w.HeaderMap.Get("Content-Type"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that no Custom JSON is rendered if code is 204
|
||||||
|
func TestContextRenderNoContentAPIJSON(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, _ := CreateTestContext(w)
|
||||||
|
|
||||||
|
c.Header("Content-Type", "application/vnd.api+json")
|
||||||
|
c.JSON(204, H{"foo": "bar"})
|
||||||
|
|
||||||
|
assert.Equal(t, 204, w.Code)
|
||||||
|
assert.Equal(t, "", w.Body.String())
|
||||||
|
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/vnd.api+json")
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that the response is serialized as JSON
|
// Tests that the response is serialized as JSON
|
||||||
// and Content-Type is set to application/json
|
// and Content-Type is set to application/json
|
||||||
func TestContextRenderIndentedJSON(t *testing.T) {
|
func TestContextRenderIndentedJSON(t *testing.T) {
|
||||||
@ -421,6 +446,18 @@ func TestContextRenderIndentedJSON(t *testing.T) {
|
|||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/json; charset=utf-8")
|
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/json; charset=utf-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that no Custom JSON is rendered if code is 204
|
||||||
|
func TestContextRenderNoContentIndentedJSON(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, _ := CreateTestContext(w)
|
||||||
|
|
||||||
|
c.IndentedJSON(204, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
|
||||||
|
|
||||||
|
assert.Equal(t, 204, w.Code)
|
||||||
|
assert.Equal(t, "", w.Body.String())
|
||||||
|
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/json; charset=utf-8")
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that the response executes the templates
|
// Tests that the response executes the templates
|
||||||
// and responds with Content-Type set to text/html
|
// and responds with Content-Type set to text/html
|
||||||
func TestContextRenderHTML(t *testing.T) {
|
func TestContextRenderHTML(t *testing.T) {
|
||||||
@ -436,6 +473,20 @@ func TestContextRenderHTML(t *testing.T) {
|
|||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
|
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that no HTML is rendered if code is 204
|
||||||
|
func TestContextRenderNoContentHTML(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, router := CreateTestContext(w)
|
||||||
|
templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
|
||||||
|
router.SetHTMLTemplate(templ)
|
||||||
|
|
||||||
|
c.HTML(204, "t", H{"name": "alexandernyquist"})
|
||||||
|
|
||||||
|
assert.Equal(t, 204, w.Code)
|
||||||
|
assert.Equal(t, "", w.Body.String())
|
||||||
|
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
|
||||||
|
}
|
||||||
|
|
||||||
// TestContextXML tests that the response is serialized as XML
|
// TestContextXML tests that the response is serialized as XML
|
||||||
// and Content-Type is set to application/xml
|
// and Content-Type is set to application/xml
|
||||||
func TestContextRenderXML(t *testing.T) {
|
func TestContextRenderXML(t *testing.T) {
|
||||||
@ -449,6 +500,18 @@ func TestContextRenderXML(t *testing.T) {
|
|||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/xml; charset=utf-8")
|
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/xml; charset=utf-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that no XML is rendered if code is 204
|
||||||
|
func TestContextRenderNoContentXML(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, _ := CreateTestContext(w)
|
||||||
|
|
||||||
|
c.XML(204, H{"foo": "bar"})
|
||||||
|
|
||||||
|
assert.Equal(t, 204, w.Code)
|
||||||
|
assert.Equal(t, "", w.Body.String())
|
||||||
|
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/xml; charset=utf-8")
|
||||||
|
}
|
||||||
|
|
||||||
// TestContextString tests that the response is returned
|
// TestContextString tests that the response is returned
|
||||||
// with Content-Type set to text/plain
|
// with Content-Type set to text/plain
|
||||||
func TestContextRenderString(t *testing.T) {
|
func TestContextRenderString(t *testing.T) {
|
||||||
@ -462,6 +525,18 @@ func TestContextRenderString(t *testing.T) {
|
|||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
|
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that no String is rendered if code is 204
|
||||||
|
func TestContextRenderNoContentString(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, _ := CreateTestContext(w)
|
||||||
|
|
||||||
|
c.String(204, "test %s %d", "string", 2)
|
||||||
|
|
||||||
|
assert.Equal(t, 204, w.Code)
|
||||||
|
assert.Equal(t, "", w.Body.String())
|
||||||
|
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
|
||||||
|
}
|
||||||
|
|
||||||
// TestContextString tests that the response is returned
|
// TestContextString tests that the response is returned
|
||||||
// with Content-Type set to text/html
|
// with Content-Type set to text/html
|
||||||
func TestContextRenderHTMLString(t *testing.T) {
|
func TestContextRenderHTMLString(t *testing.T) {
|
||||||
@ -476,6 +551,19 @@ func TestContextRenderHTMLString(t *testing.T) {
|
|||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
|
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that no HTML String is rendered if code is 204
|
||||||
|
func TestContextRenderNoContentHTMLString(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, _ := CreateTestContext(w)
|
||||||
|
|
||||||
|
c.Header("Content-Type", "text/html; charset=utf-8")
|
||||||
|
c.String(204, "<html>%s %d</html>", "string", 3)
|
||||||
|
|
||||||
|
assert.Equal(t, 204, w.Code)
|
||||||
|
assert.Equal(t, "", w.Body.String())
|
||||||
|
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
|
||||||
|
}
|
||||||
|
|
||||||
// TestContextData tests that the response can be written from `bytesting`
|
// TestContextData tests that the response can be written from `bytesting`
|
||||||
// with specified MIME type
|
// with specified MIME type
|
||||||
func TestContextRenderData(t *testing.T) {
|
func TestContextRenderData(t *testing.T) {
|
||||||
@ -489,6 +577,18 @@ func TestContextRenderData(t *testing.T) {
|
|||||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/csv")
|
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/csv")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests that no Custom Data is rendered if code is 204
|
||||||
|
func TestContextRenderNoContentData(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, _ := CreateTestContext(w)
|
||||||
|
|
||||||
|
c.Data(204, "text/csv", []byte(`foo,bar`))
|
||||||
|
|
||||||
|
assert.Equal(t, 204, w.Code)
|
||||||
|
assert.Equal(t, "", w.Body.String())
|
||||||
|
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/csv")
|
||||||
|
}
|
||||||
|
|
||||||
func TestContextRenderSSE(t *testing.T) {
|
func TestContextRenderSSE(t *testing.T) {
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
c, _ := CreateTestContext(w)
|
c, _ := CreateTestContext(w)
|
||||||
|
|||||||
@ -10,8 +10,8 @@ import (
|
|||||||
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/manucorporat/sse"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"gopkg.in/gin-contrib/sse.v0"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMiddlewareGeneralCase(t *testing.T) {
|
func TestMiddlewareGeneralCase(t *testing.T) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user