Merge 4a1434ad5e5d05845e6331caa25a240f45c04e9f into d5b353c5d5a560322e6d96121c814115562501f7

This commit is contained in:
David Martorana 2017-06-19 16:54:37 +00:00 committed by GitHub
commit 9fbe44d98f
3 changed files with 45 additions and 39 deletions

View File

@ -422,47 +422,43 @@ func (c *Context) Cookie(name string) (string, error) {
return val, nil
}
func (c *Context) Render(code int, r render.Render) {
func (c *Context) Render(code int, r render.Render) error {
c.Status(code)
if err := r.Render(c.Writer); err != nil {
panic(err)
}
return r.Render(c.Writer)
}
// HTML renders the HTTP template specified by its file name.
// It also updates the HTTP code and sets the Content-Type as "text/html".
// See http://golang.org/doc/articles/wiki/
func (c *Context) HTML(code int, name string, obj interface{}) {
func (c *Context) HTML(code int, name string, obj interface{}) error {
instance := c.engine.HTMLRender.Instance(name, obj)
c.Render(code, instance)
return c.Render(code, instance)
}
// IndentedJSON serializes the given struct as pretty JSON (indented + endlines) into the response body.
// It also sets the Content-Type as "application/json".
// WARNING: we recommend to use this only for development propuses since printing pretty JSON is
// more CPU and bandwidth consuming. Use Context.JSON() instead.
func (c *Context) IndentedJSON(code int, obj interface{}) {
c.Render(code, render.IndentedJSON{Data: obj})
func (c *Context) IndentedJSON(code int, obj interface{}) error {
return c.Render(code, render.IndentedJSON{Data: obj})
}
// JSON serializes the given struct as JSON into the response body.
// 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{}) error {
c.Status(code)
if err := render.WriteJSON(c.Writer, obj); err != nil {
panic(err)
}
return render.WriteJSON(c.Writer, obj)
}
// XML serializes the given struct as XML into the response body.
// It also sets the Content-Type as "application/xml".
func (c *Context) XML(code int, obj interface{}) {
c.Render(code, render.XML{Data: obj})
func (c *Context) XML(code int, obj interface{}) error {
return c.Render(code, render.XML{Data: obj})
}
// YAML serializes the given struct as YAML into the response body.
func (c *Context) YAML(code int, obj interface{}) {
c.Render(code, render.YAML{Data: obj})
func (c *Context) YAML(code int, obj interface{}) error {
return c.Render(code, render.YAML{Data: obj})
}
// String writes the given string into the response body.
@ -472,8 +468,8 @@ func (c *Context) String(code int, format string, values ...interface{}) {
}
// Redirect returns a HTTP redirect to the specific location.
func (c *Context) Redirect(code int, location string) {
c.Render(-1, render.Redirect{
func (c *Context) Redirect(code int, location string) error {
return c.Render(-1, render.Redirect{
Code: code,
Location: location,
Request: c.Request,
@ -481,8 +477,8 @@ func (c *Context) Redirect(code int, location string) {
}
// Data writes some data into the body stream and updates the HTTP code.
func (c *Context) Data(code int, contentType string, data []byte) {
c.Render(code, render.Data{
func (c *Context) Data(code int, contentType string, data []byte) error {
return c.Render(code, render.Data{
ContentType: contentType,
Data: data,
})
@ -494,8 +490,8 @@ func (c *Context) File(filepath string) {
}
// SSEvent writes a Server-Sent Event into the body stream.
func (c *Context) SSEvent(name string, message interface{}) {
c.Render(-1, sse.Event{
func (c *Context) SSEvent(name string, message interface{}) error {
return c.Render(-1, sse.Event{
Event: name,
Data: message,
})

View File

@ -351,8 +351,9 @@ func TestContextGetCookie(t *testing.T) {
// and Content-Type is set to application/json
func TestContextRenderJSON(t *testing.T) {
c, w, _ := CreateTestContext()
c.JSON(201, H{"foo": "bar"})
e := c.JSON(201, H{"foo": "bar"})
assert.NoError(t, e)
assert.Equal(t, w.Code, 201)
assert.Equal(t, w.Body.String(), "{\"foo\":\"bar\"}\n")
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/json; charset=utf-8")
@ -363,8 +364,9 @@ func TestContextRenderJSON(t *testing.T) {
func TestContextRenderAPIJSON(t *testing.T) {
c, w, _ := CreateTestContext()
c.Header("Content-Type", "application/vnd.api+json")
c.JSON(201, H{"foo": "bar"})
e := c.JSON(201, H{"foo": "bar"})
assert.NoError(t, e)
assert.Equal(t, w.Code, 201)
assert.Equal(t, w.Body.String(), "{\"foo\":\"bar\"}\n")
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/vnd.api+json")
@ -374,8 +376,9 @@ func TestContextRenderAPIJSON(t *testing.T) {
// and Content-Type is set to application/json
func TestContextRenderIndentedJSON(t *testing.T) {
c, w, _ := CreateTestContext()
c.IndentedJSON(201, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
err := c.IndentedJSON(201, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
assert.NoError(t, err)
assert.Equal(t, w.Code, 201)
assert.Equal(t, w.Body.String(), "{\n \"bar\": \"foo\",\n \"foo\": \"bar\",\n \"nested\": {\n \"foo\": \"bar\"\n }\n}")
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/json; charset=utf-8")
@ -388,8 +391,9 @@ func TestContextRenderHTML(t *testing.T) {
templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
router.SetHTMLTemplate(templ)
c.HTML(201, "t", H{"name": "alexandernyquist"})
err := c.HTML(201, "t", H{"name": "alexandernyquist"})
assert.NoError(t, err)
assert.Equal(t, w.Code, 201)
assert.Equal(t, w.Body.String(), "Hello alexandernyquist")
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
@ -399,8 +403,9 @@ func TestContextRenderHTML(t *testing.T) {
// and Content-Type is set to application/xml
func TestContextRenderXML(t *testing.T) {
c, w, _ := CreateTestContext()
c.XML(201, H{"foo": "bar"})
err := c.XML(201, H{"foo": "bar"})
assert.NoError(t, err)
assert.Equal(t, w.Code, 201)
assert.Equal(t, w.Body.String(), "<map><foo>bar</foo></map>")
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/xml; charset=utf-8")
@ -433,8 +438,9 @@ func TestContextRenderHTMLString(t *testing.T) {
// with specified MIME type
func TestContextRenderData(t *testing.T) {
c, w, _ := CreateTestContext()
c.Data(201, "text/csv", []byte(`foo,bar`))
err := c.Data(201, "text/csv", []byte(`foo,bar`))
assert.NoError(t, err)
assert.Equal(t, w.Code, 201)
assert.Equal(t, w.Body.String(), "foo,bar")
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/csv")
@ -469,8 +475,9 @@ func TestContextRenderFile(t *testing.T) {
// and Content-Type is set to application/x-yaml
func TestContextRenderYAML(t *testing.T) {
c, w, _ := CreateTestContext()
c.YAML(201, H{"foo": "bar"})
err := c.YAML(201, H{"foo": "bar"})
assert.NoError(t, err)
assert.Equal(t, w.Code, 201)
assert.Equal(t, w.Body.String(), "foo: bar\n")
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/x-yaml; charset=utf-8")
@ -496,10 +503,12 @@ func TestContextHeaders(t *testing.T) {
func TestContextRenderRedirectWithRelativePath(t *testing.T) {
c, w, _ := CreateTestContext()
c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
assert.Panics(t, func() { c.Redirect(299, "/new_path") })
assert.Panics(t, func() { c.Redirect(309, "/new_path") })
assert.Error(t, c.Redirect(299, "/new_path"))
assert.Error(t, c.Redirect(309, "/new_path"))
err := c.Redirect(301, "/path")
assert.NoError(t, err)
c.Redirect(301, "/path")
c.Writer.WriteHeaderNow()
assert.Equal(t, w.Code, 301)
assert.Equal(t, w.Header().Get("Location"), "/path")
@ -528,12 +537,12 @@ func TestContextRenderRedirectWith201(t *testing.T) {
func TestContextRenderRedirectAll(t *testing.T) {
c, _, _ := CreateTestContext()
c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
assert.Panics(t, func() { c.Redirect(200, "/resource") })
assert.Panics(t, func() { c.Redirect(202, "/resource") })
assert.Panics(t, func() { c.Redirect(299, "/resource") })
assert.Panics(t, func() { c.Redirect(309, "/resource") })
assert.NotPanics(t, func() { c.Redirect(300, "/resource") })
assert.NotPanics(t, func() { c.Redirect(308, "/resource") })
assert.Error(t, c.Redirect(200, "/resource"))
assert.Error(t, c.Redirect(202, "/resource"))
assert.Error(t, c.Redirect(299, "/resource"))
assert.Error(t, c.Redirect(309, "/resource"))
assert.NoError(t, c.Redirect(300, "/resource"))
assert.NoError(t, c.Redirect(308, "/resource"))
}
func TestContextNegotiationFormat(t *testing.T) {

View File

@ -5,6 +5,7 @@
package render
import (
"errors"
"fmt"
"net/http"
)
@ -17,7 +18,7 @@ type Redirect struct {
func (r Redirect) Render(w http.ResponseWriter) error {
if (r.Code < 300 || r.Code > 308) && r.Code != 201 {
panic(fmt.Sprintf("Cannot redirect with status code %d", r.Code))
return errors.New(fmt.Sprintf("Cannot redirect with status code %d", r.Code))
}
http.Redirect(w, r.Request, r.Location, r.Code)
return nil