mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-14 04:08:15 +08:00
Merge 22ae924b10f959da8fcd360b84281553f03f633a into c3d1092b3b48addf6f9cd00fe274ec3bd14650eb
This commit is contained in:
commit
823fb36ba1
60
context.go
60
context.go
@ -1280,32 +1280,64 @@ type Negotiate struct {
|
||||
TOMLData any
|
||||
}
|
||||
|
||||
// Negotiate calls different Render according to acceptable Accept format.
|
||||
func (c *Context) Negotiate(code int, config Negotiate) {
|
||||
switch c.NegotiateFormat(config.Offered...) {
|
||||
case binding.MIMEJSON:
|
||||
func NewNegotiate(offered []string) Negotiate {
|
||||
return Negotiate{Offered: offered}
|
||||
}
|
||||
func (receiver Negotiate) WithData(data any) Negotiate {
|
||||
receiver.Data = data
|
||||
return receiver
|
||||
}
|
||||
|
||||
// NegotiationRenderFunc is responsible for rendering data in a specific format.
|
||||
type NegotiationRenderFunc func(status int, config Negotiate, c *Context)
|
||||
|
||||
func AddNegotiationRenderMapping(mimeType string, binding NegotiationRenderFunc) {
|
||||
negotiationRenderMappings[mimeType] = binding
|
||||
}
|
||||
|
||||
// All predefined negotiationRenderMappings - associate a content type
|
||||
// with a NegotiationRenderFunc, which is responsible for rendering
|
||||
// data in a specific format.
|
||||
var negotiationRenderMappings = map[string]NegotiationRenderFunc{
|
||||
binding.MIMEJSON: func(code int, config Negotiate, c *Context) {
|
||||
data := chooseData(config.JSONData, config.Data)
|
||||
c.JSON(code, data)
|
||||
|
||||
case binding.MIMEHTML:
|
||||
},
|
||||
binding.MIMEHTML: func(code int, config Negotiate, c *Context) {
|
||||
data := chooseData(config.HTMLData, config.Data)
|
||||
c.HTML(code, config.HTMLName, data)
|
||||
|
||||
case binding.MIMEXML:
|
||||
},
|
||||
binding.MIMEXML: func(code int, config Negotiate, c *Context) {
|
||||
data := chooseData(config.XMLData, config.Data)
|
||||
c.XML(code, data)
|
||||
|
||||
case binding.MIMEYAML, binding.MIMEYAML2:
|
||||
},
|
||||
binding.MIMEYAML: func(code int, config Negotiate, c *Context) {
|
||||
data := chooseData(config.YAMLData, config.Data)
|
||||
c.YAML(code, data)
|
||||
|
||||
case binding.MIMETOML:
|
||||
},
|
||||
binding.MIMEYAML2: func(code int, config Negotiate, c *Context) {
|
||||
data := chooseData(config.YAMLData, config.Data)
|
||||
c.YAML(code, data)
|
||||
},
|
||||
binding.MIMETOML: func(code int, config Negotiate, c *Context) {
|
||||
data := chooseData(config.TOMLData, config.Data)
|
||||
c.TOML(code, data)
|
||||
},
|
||||
binding.MIMEPROTOBUF: func(code int, config Negotiate, c *Context) {
|
||||
c.ProtoBuf(code, config.Data)
|
||||
},
|
||||
}
|
||||
|
||||
default:
|
||||
c.AbortWithError(http.StatusNotAcceptable, errors.New("the accepted formats are not offered by the server")) //nolint: errcheck
|
||||
// Negotiate calls different Render according to acceptable Accept format.
|
||||
func (c *Context) Negotiate(code int, config Negotiate) {
|
||||
|
||||
accepted := c.NegotiateFormat(config.Offered...)
|
||||
if fn, ok := negotiationRenderMappings[accepted]; ok {
|
||||
fn(code, config, c)
|
||||
return
|
||||
}
|
||||
c.AbortWithError(http.StatusNotAcceptable, errors.New("the accepted formats are not offered by the server")) //nolint: errcheck
|
||||
|
||||
}
|
||||
|
||||
// NegotiateFormat returns an acceptable Accept format.
|
||||
|
@ -1615,6 +1615,44 @@ func TestContextNegotiationWithHTML(t *testing.T) {
|
||||
assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
|
||||
}
|
||||
|
||||
func TestContextNegotiationWithProto(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := CreateTestContext(w)
|
||||
c.Request, _ = http.NewRequest(http.MethodPost, "", nil)
|
||||
|
||||
c.Negotiate(http.StatusOK, Negotiate{
|
||||
Offered: []string{binding.MIMEPROTOBUF},
|
||||
Data: &testdata.Test{},
|
||||
})
|
||||
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
assert.Equal(t, 0, w.Body.Len())
|
||||
assert.Equal(t, "application/x-protobuf", w.Header().Get("Content-Type"))
|
||||
}
|
||||
|
||||
func TestContextNegotiationWithCustom(t *testing.T) {
|
||||
|
||||
contentType := "application/whatever"
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := CreateTestContext(w)
|
||||
c.Request, _ = http.NewRequest(http.MethodPost, "", nil)
|
||||
|
||||
AddNegotiationRenderMapping(contentType, func(status int, config Negotiate, c *Context) {
|
||||
data := config.Data.([]byte)
|
||||
c.Data(status, contentType, data)
|
||||
})
|
||||
|
||||
c.Negotiate(http.StatusOK, Negotiate{
|
||||
Offered: []string{contentType},
|
||||
Data: []byte("Hello World"),
|
||||
})
|
||||
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
assert.Equal(t, "Hello World", w.Body.String())
|
||||
assert.Equal(t, contentType, w.Header().Get("Content-Type"))
|
||||
}
|
||||
|
||||
func TestContextNegotiationNotSupport(t *testing.T) {
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := CreateTestContext(w)
|
||||
|
Loading…
x
Reference in New Issue
Block a user