Skip to content

Commit ee909dc

Browse files
authored
Add RegisterBodyEncoder (#656)
1 parent d5c7ac5 commit ee909dc

2 files changed

Lines changed: 71 additions & 2 deletions

File tree

openapi3filter/req_resp_encoder.go

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,34 @@ func encodeBody(body interface{}, mediaType string) ([]byte, error) {
1616
return encoder(body)
1717
}
1818

19-
type bodyEncoder func(body interface{}) ([]byte, error)
19+
type BodyEncoder func(body interface{}) ([]byte, error)
2020

21-
var bodyEncoders = map[string]bodyEncoder{
21+
var bodyEncoders = map[string]BodyEncoder{
2222
"application/json": json.Marshal,
2323
}
24+
25+
func RegisterBodyEncoder(contentType string, encoder BodyEncoder) {
26+
if contentType == "" {
27+
panic("contentType is empty")
28+
}
29+
if encoder == nil {
30+
panic("encoder is not defined")
31+
}
32+
bodyEncoders[contentType] = encoder
33+
}
34+
35+
// This call is not thread-safe: body encoders should not be created/destroyed by multiple goroutines.
36+
func UnregisterBodyEncoder(contentType string) {
37+
if contentType == "" {
38+
panic("contentType is empty")
39+
}
40+
delete(bodyEncoders, contentType)
41+
}
42+
43+
// RegisteredBodyEncoder returns the registered body encoder for the given content type.
44+
//
45+
// If no encoder was registered for the given content type, nil is returned.
46+
// This call is not thread-safe: body encoders should not be created/destroyed by multiple goroutines.
47+
func RegisteredBodyEncoder(contentType string) BodyEncoder {
48+
return bodyEncoders[contentType]
49+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package openapi3filter
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"strings"
7+
"testing"
8+
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func TestRegisterAndUnregisterBodyEncoder(t *testing.T) {
13+
var encoder BodyEncoder
14+
encoder = func(body interface{}) (data []byte, err error) {
15+
return []byte(strings.Join(body.([]string), ",")), nil
16+
}
17+
contentType := "text/csv"
18+
h := make(http.Header)
19+
h.Set(headerCT, contentType)
20+
21+
originalEncoder := RegisteredBodyEncoder(contentType)
22+
require.Nil(t, originalEncoder)
23+
24+
RegisterBodyEncoder(contentType, encoder)
25+
require.Equal(t, fmt.Sprintf("%v", encoder), fmt.Sprintf("%v", RegisteredBodyEncoder(contentType)))
26+
27+
body := []string{"foo", "bar"}
28+
got, err := encodeBody(body, contentType)
29+
30+
require.NoError(t, err)
31+
require.Equal(t, []byte("foo,bar"), got)
32+
33+
UnregisterBodyEncoder(contentType)
34+
35+
originalEncoder = RegisteredBodyEncoder(contentType)
36+
require.Nil(t, originalEncoder)
37+
38+
_, err = encodeBody(body, contentType)
39+
require.Equal(t, &ParseError{
40+
Kind: KindUnsupportedFormat,
41+
Reason: prefixUnsupportedCT + ` "text/csv"`,
42+
}, err)
43+
}

0 commit comments

Comments
 (0)