feat(context): add Protocol Buffers support to content negotiation (#4423)

Co-authored-by: 1911860538 <alxps1911@gmail.com>
This commit is contained in:
Name 2025-11-07 11:59:58 +08:00 committed by GitHub
parent 0c0e99d253
commit acc55e049e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 40 additions and 8 deletions

View File

@ -39,6 +39,7 @@ const (
MIMEYAML = binding.MIMEYAML MIMEYAML = binding.MIMEYAML
MIMEYAML2 = binding.MIMEYAML2 MIMEYAML2 = binding.MIMEYAML2
MIMETOML = binding.MIMETOML MIMETOML = binding.MIMETOML
MIMEPROTOBUF = binding.MIMEPROTOBUF
) )
// BodyBytesKey indicates a default body bytes key. // BodyBytesKey indicates a default body bytes key.
@ -1280,14 +1281,15 @@ func (c *Context) Stream(step func(w io.Writer) bool) bool {
// Negotiate contains all negotiations data. // Negotiate contains all negotiations data.
type Negotiate struct { type Negotiate struct {
Offered []string Offered []string
HTMLName string HTMLName string
HTMLData any HTMLData any
JSONData any JSONData any
XMLData any XMLData any
YAMLData any YAMLData any
Data any Data any
TOMLData any TOMLData any
PROTOBUFData any
} }
// Negotiate calls different Render according to acceptable Accept format. // Negotiate calls different Render according to acceptable Accept format.
@ -1313,6 +1315,10 @@ func (c *Context) Negotiate(code int, config Negotiate) {
data := chooseData(config.TOMLData, config.Data) data := chooseData(config.TOMLData, config.Data)
c.TOML(code, data) c.TOML(code, data)
case binding.MIMEPROTOBUF:
data := chooseData(config.PROTOBUFData, config.Data)
c.ProtoBuf(code, data)
default: default:
c.AbortWithError(http.StatusNotAcceptable, errors.New("the accepted formats are not offered by the server")) //nolint: errcheck c.AbortWithError(http.StatusNotAcceptable, errors.New("the accepted formats are not offered by the server")) //nolint: errcheck
} }

View File

@ -1628,6 +1628,32 @@ func TestContextNegotiationWithHTML(t *testing.T) {
assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type")) assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
} }
func TestContextNegotiationWithPROTOBUF(t *testing.T) {
w := httptest.NewRecorder()
c, _ := CreateTestContext(w)
c.Request = httptest.NewRequest(http.MethodPost, "/", nil)
reps := []int64{int64(1), int64(2)}
label := "test"
data := &testdata.Test{
Label: &label,
Reps: reps,
}
c.Negotiate(http.StatusCreated, Negotiate{
Offered: []string{MIMEPROTOBUF, MIMEJSON, MIMEXML},
Data: data,
})
// Marshal original data for comparison
protoData, err := proto.Marshal(data)
require.NoError(t, err)
assert.Equal(t, http.StatusCreated, w.Code)
assert.Equal(t, string(protoData), w.Body.String())
assert.Equal(t, "application/x-protobuf", w.Header().Get("Content-Type"))
}
func TestContextNegotiationNotSupport(t *testing.T) { func TestContextNegotiationNotSupport(t *testing.T) {
w := httptest.NewRecorder() w := httptest.NewRecorder()
c, _ := CreateTestContext(w) c, _ := CreateTestContext(w)