mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-15 21:06:39 +08:00
Merge 743cdd1a39fefa28e4e6f86d81a02b82512b433d into 72ffff6e442e76b3109322d71a2b64a1ba0fcf74
This commit is contained in:
commit
c9fa87b1be
12
context.go
12
context.go
@ -26,6 +26,7 @@ const (
|
||||
MIMEHTML = binding.MIMEHTML
|
||||
MIMEXML = binding.MIMEXML
|
||||
MIMEXML2 = binding.MIMEXML2
|
||||
MIMEPROTOBUF = binding.MIMEPROTOBUF
|
||||
MIMEPlain = binding.MIMEPlain
|
||||
MIMEPOSTForm = binding.MIMEPOSTForm
|
||||
MIMEMultipartPOSTForm = binding.MIMEMultipartPOSTForm
|
||||
@ -426,6 +427,12 @@ func (c *Context) XML(code int, obj interface{}) {
|
||||
c.Render(code, render.XML{Data: obj})
|
||||
}
|
||||
|
||||
// Protobuf serializes the given struct as PB binary-stream into response body
|
||||
// It also sets the Content-Type as "application/x-protobuf"
|
||||
func (c *Context) Protobuf(code int, obj interface{}) {
|
||||
c.Render(code, render.Protobuf{Data: obj})
|
||||
}
|
||||
|
||||
// String writes the given string into the response body.
|
||||
func (c *Context) String(code int, format string, values ...interface{}) {
|
||||
c.Status(code)
|
||||
@ -489,6 +496,7 @@ type Negotiate struct {
|
||||
HTMLData interface{}
|
||||
JSONData interface{}
|
||||
XMLData interface{}
|
||||
PBData interface{}
|
||||
Data interface{}
|
||||
}
|
||||
|
||||
@ -506,6 +514,10 @@ func (c *Context) Negotiate(code int, config Negotiate) {
|
||||
data := chooseData(config.XMLData, config.Data)
|
||||
c.XML(code, data)
|
||||
|
||||
case binding.MIMEPROTOBUF:
|
||||
data := chooseData(config.PBData, config.Data)
|
||||
c.Protobuf(code, data)
|
||||
|
||||
default:
|
||||
c.AbortWithError(http.StatusNotAcceptable, errors.New("the accepted formats are not offered by the server"))
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin/binding/example"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/manucorporat/sse"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@ -374,6 +376,16 @@ func TestContextRenderXML(t *testing.T) {
|
||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/xml; charset=utf-8")
|
||||
}
|
||||
|
||||
// TestContextRenderProtobuf tests that the response is serialized as Protobuf binary-stream
|
||||
// and Content-Type is set to application/x-protobuf
|
||||
func TestContextRenderProtobuf(t *testing.T) {
|
||||
c, w, _ := CreateTestContext()
|
||||
c.Protobuf(201, &example.Test{Label: proto.String("test")})
|
||||
|
||||
assert.Equal(t, w.Code, 201)
|
||||
assert.Equal(t, w.HeaderMap.Get("Content-Type"), "application/x-protobuf")
|
||||
}
|
||||
|
||||
// TestContextString tests that the response is returned
|
||||
// with Content-Type set to text/plain
|
||||
func TestContextRenderString(t *testing.T) {
|
||||
@ -500,15 +512,17 @@ func TestContextNegotiationFormat(t *testing.T) {
|
||||
assert.Panics(t, func() { c.NegotiateFormat() })
|
||||
assert.Equal(t, c.NegotiateFormat(MIMEJSON, MIMEXML), MIMEJSON)
|
||||
assert.Equal(t, c.NegotiateFormat(MIMEHTML, MIMEJSON), MIMEHTML)
|
||||
assert.Equal(t, c.NegotiateFormat(MIMEPROTOBUF, MIMEPROTOBUF), MIMEPROTOBUF)
|
||||
}
|
||||
|
||||
func TestContextNegotiationFormatWithAccept(t *testing.T) {
|
||||
c, _, _ := CreateTestContext()
|
||||
c.Request, _ = http.NewRequest("POST", "/", nil)
|
||||
c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
|
||||
c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml,application/x-protobuf;q=0.9,*/*;q=0.8")
|
||||
|
||||
assert.Equal(t, c.NegotiateFormat(MIMEJSON, MIMEXML), MIMEXML)
|
||||
assert.Equal(t, c.NegotiateFormat(MIMEXML, MIMEHTML), MIMEHTML)
|
||||
assert.Equal(t, c.NegotiateFormat(MIMEPROTOBUF, MIMEPROTOBUF), MIMEPROTOBUF)
|
||||
assert.Equal(t, c.NegotiateFormat(MIMEJSON), "")
|
||||
}
|
||||
|
||||
|
24
render/protobuf.go
Normal file
24
render/protobuf.go
Normal file
@ -0,0 +1,24 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"github.com/golang/protobuf/proto"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Protobuf struct {
|
||||
Data interface{}
|
||||
}
|
||||
|
||||
var pbContentType = []string{"application/x-protobuf"}
|
||||
|
||||
func (r Protobuf) Render(w http.ResponseWriter) error {
|
||||
writeContentType(w, pbContentType)
|
||||
encoded, err := proto.Marshal(r.Data.(proto.Message))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = w.Write(encoded); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
@ -10,6 +10,8 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin/binding/example"
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -82,6 +84,19 @@ func TestRenderXML(t *testing.T) {
|
||||
assert.Equal(t, w.Header().Get("Content-Type"), "application/xml; charset=utf-8")
|
||||
}
|
||||
|
||||
func TestRenderProtobuf(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
data := &example.Test{
|
||||
Label: proto.String("test"),
|
||||
}
|
||||
|
||||
err := (Protobuf{data}).Render(w)
|
||||
|
||||
assert.NoError(t, err)
|
||||
// assert.Equal(t, w.Body.String(), "<map><foo>bar</foo></map>")
|
||||
// assert.Equal(t, w.Header().Get("Content-Type"), "application/xml; charset=utf-8")
|
||||
}
|
||||
|
||||
func TestRenderRedirect(t *testing.T) {
|
||||
// TODO
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user