diff --git a/context.go b/context.go index 046f284e..ba962976 100644 --- a/context.go +++ b/context.go @@ -413,9 +413,22 @@ func (c *Context) QueryMap(key string) map[string]string { return dicts } +// QueryMultiMap returns a multimap for a given query key. +func (c *Context) QueryMultiMap(key string) map[string][]string { + dicts, _ := c.GetQueryMultiMap(key) + return dicts +} + // GetQueryMap returns a map for a given query key, plus a boolean value // whether at least one value exists for the given key. func (c *Context) GetQueryMap(key string) (map[string]string, bool) { + dicts, exists := c.GetQueryMultiMap(key) + return filterAllValuesButTheFirstOne(dicts), exists +} + +// GetQueryMultiMap returns a multimap for a given query key, plus a boolean value +// whether at least one value exists for the given key. +func (c *Context) GetQueryMultiMap(key string) (map[string][]string, bool) { c.getQueryCache() return c.get(c.queryCache, key) } @@ -491,24 +504,37 @@ func (c *Context) PostFormMap(key string) map[string]string { // whether at least one value exists for the given key. func (c *Context) GetPostFormMap(key string) (map[string]string, bool) { c.getFormCache() - return c.get(c.formCache, key) + dicts, exists := c.get(c.formCache, key) + return filterAllValuesButTheFirstOne(dicts), exists } -// get is an internal method and returns a map which satisfy conditions. -func (c *Context) get(m map[string][]string, key string) (map[string]string, bool) { - dicts := make(map[string]string) +// get is an internal method and returns a multimap which satisfy conditions. +func (c *Context) get(m map[string][]string, key string) (map[string][]string, bool) { + dicts := make(map[string][]string) exist := false for k, v := range m { if i := strings.IndexByte(k, '['); i >= 1 && k[0:i] == key { if j := strings.IndexByte(k[i+1:], ']'); j >= 1 { exist = true - dicts[k[i+1:][:j]] = v[0] + dicts[k[i+1:][:j]] = v } } } return dicts, exist } +// filterAllValuesButTheFirstOne returns a map where the values correspond +// to the first value for each key in the multimap given as input. +func filterAllValuesButTheFirstOne(m map[string][]string) map[string]string { + result := map[string]string{} + + for k, v := range m { + result[k] = v[0] + } + + return result +} + // FormFile returns the first file for the provided form key. func (c *Context) FormFile(name string) (*multipart.FileHeader, error) { if c.Request.MultipartForm == nil { diff --git a/context_test.go b/context_test.go index f7bb0f51..ab011681 100644 --- a/context_test.go +++ b/context_test.go @@ -414,7 +414,7 @@ func TestContextQueryAndPostForm(t *testing.T) { c, _ := CreateTestContext(httptest.NewRecorder()) body := bytes.NewBufferString("foo=bar&page=11&both=&foo=second") c.Request, _ = http.NewRequest("POST", - "/?both=GET&id=main&id=omit&array[]=first&array[]=second&ids[a]=hi&ids[b]=3.14", body) + "/?both=GET&id=main&id=omit&array[]=first&array[]=second&ids[a]=hi&ids[a]=bye&ids[b]=3.14", body) c.Request.Header.Add("Content-Type", MIMEPOSTForm) assert.Equal(t, "bar", c.DefaultPostForm("foo", "none")) @@ -506,6 +506,30 @@ func TestContextQueryAndPostForm(t *testing.T) { dicts = c.QueryMap("nokey") assert.Equal(t, 0, len(dicts)) + + multiDicts, ok := c.GetQueryMultiMap("ids") + assert.True(t, ok) + assert.Equal(t, []string{"hi", "bye"}, multiDicts["a"]) + assert.Equal(t, []string{"3.14"}, multiDicts["b"]) + + multiDicts, ok = c.GetQueryMultiMap("nokey") + assert.False(t, ok) + assert.Equal(t, 0, len(multiDicts)) + + multiDicts, ok = c.GetQueryMultiMap("both") + assert.False(t, ok) + assert.Equal(t, 0, len(multiDicts)) + + multiDicts, ok = c.GetQueryMultiMap("array") + assert.False(t, ok) + assert.Equal(t, 0, len(multiDicts)) + + multiDicts = c.QueryMultiMap("ids") + assert.Equal(t, []string{"hi", "bye"}, multiDicts["a"]) + assert.Equal(t, []string{"3.14"}, multiDicts["b"]) + + multiDicts = c.QueryMultiMap("nokey") + assert.Equal(t, 0, len(multiDicts)) } func TestContextPostFormMultipart(t *testing.T) {