Skip to content

Commit

Permalink
Add Decoders
Browse files Browse the repository at this point in the history
  • Loading branch information
razonyang committed Feb 5, 2020
1 parent 7de0974 commit 9c32eb0
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 15 deletions.
36 changes: 23 additions & 13 deletions form.go
Expand Up @@ -25,45 +25,55 @@ const (
ContentTypeXML = "application/xml"
)

var decoders = make(map[string]Decoder)
var defaultDecoders = &Decoders{}

var defaultDecoder = schema.NewDecoder()
var defaultMaxMemory int64 = 10 * 1024 * 1024

func init() {
}

func init() {
defaultDecoder.IgnoreUnknownKeys(true)
defaultDecoder.SetAliasTag("json")

Register(ContentTypeForm, NewForm(defaultDecoder))
Register(ContentTypeMultipartForm, NewMultipartForm(defaultMaxMemory))
Register(ContentTypeJSON, JSON)
Register(ContentTypeXML, XML)
defaultDecoders.Register(ContentTypeForm, NewForm(defaultDecoder))
defaultDecoders.Register(ContentTypeMultipartForm, NewMultipartForm(defaultMaxMemory))
defaultDecoders.Register(ContentTypeJSON, JSON)
defaultDecoders.Register(ContentTypeXML, XML)
}

// Register a decoder for the given content type.
func Register(contentType string, decoder Decoder) {
decoders[contentType] = decoder
defaultDecoders.Register(contentType, decoder)
}

// Decoder is a function that decode data from request into v.
type Decoder func(req *http.Request, v interface{}) error

// Decode data from a request into v, v should be a pointer.
func Decode(r *http.Request, v interface{}) error {
return defaultDecoders.Decode(r, v)
}

// Decoders is a map that mapping from content type to decoder.
type Decoders map[string]Decoder

// Register a decoder for the given content type.
func (d *Decoders) Register(contentType string, decoder Decoder) {
(*d)[contentType] = decoder
}

// Decode data from a request into v, v should be a pointer.
func (d *Decoders) Decode(r *http.Request, v interface{}) error {
contentType, err := parseContentType(r)
if err != nil {
return err
}
if decoder, ok := decoders[contentType]; ok {
if decoder, ok := (*d)[contentType]; ok {
return decoder(r, v)
}

return errors.New("Unsupported content type: " + contentType)
}

// Decoder is a function that decode data from request into v.
type Decoder func(req *http.Request, v interface{}) error

func parseContentType(r *http.Request) (string, error) {
header := r.Header.Get(ContentType)
contentType, _, err := mime.ParseMediaType(header)
Expand Down
4 changes: 2 additions & 2 deletions form_test.go
Expand Up @@ -28,7 +28,7 @@ func TestRegister(t *testing.T) {
}
contentType := "content/type"
Register(contentType, decoder)
actual, ok := decoders[contentType]
actual, ok := (*defaultDecoders)[contentType]
if !ok {
t.Error("Failed to register decoder")
}
Expand Down Expand Up @@ -200,7 +200,7 @@ func TestParseContentType(t *testing.T) {
}

func TestDecode(t *testing.T) {
delete(decoders, "application/json")
delete((*defaultDecoders), "application/json")
req := httptest.NewRequest(http.MethodPost, "/login", nil)
req.Header.Set("Content-Type", "application/json")
v := login{}
Expand Down

0 comments on commit 9c32eb0

Please sign in to comment.