diff --git a/form.go b/form.go index 5dc1ca7..2aad714 100644 --- a/form.go +++ b/form.go @@ -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) diff --git a/form_test.go b/form_test.go index ff9daa5..6f0a014 100644 --- a/form_test.go +++ b/form_test.go @@ -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") } @@ -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{}