diff --git a/context.go b/context.go index 1f356515..b0f9bf1b 100644 --- a/context.go +++ b/context.go @@ -15,6 +15,7 @@ import ( "net/url" "os" "path/filepath" + "strconv" "strings" "sync" "time" @@ -644,6 +645,61 @@ func (c *Context) GetQueryMap(key string) (map[string]string, bool) { return c.get(c.queryCache, key) } +// QueryBool returns a value of boolean type for given query key. +// HINT: if given key is not exist or not valid, it returns false. +// +// GET /?name=alex&force=true&delivery= +// c.QueryBool("force") == true +// c.QueryBool("name") == false +// c.QueryBool("delivery") == false +func (c *Context) QueryBool(key string) (bool, error) { + + value, _ := c.GetQuery(key) + boolValue, err := strconv.ParseBool(value) + + return boolValue, err +} + +// GetQueryBoolDefault returns the keyed boolean url query value if it exists and valid, +// otherwise it returns the specified defaultValue string. +// +// GET /?name=alex&force=true&delivery= +// c.GetQueryBoolDefault("force", false) == true +// c.GetQueryBoolDefault("name", false) == false +// c.GetQueryBoolDefault("delivery", false) == false +func (c *Context) GetQueryBoolDefault(key string, defaultValue bool) bool { + + if value, ok := c.GetQuery(key); ok { + boolValue, err := strconv.ParseBool(value) + if err != nil { + return defaultValue + } + return boolValue + } + + return defaultValue +} + +// GetQueryBool is like QueryBool(), it returns the keyed url query value but in boolean, +// if key exists and valid it returns (value, true) +// but if key is not exist or not valid, it returns (true, false) +// +// GET /?name=alex&force=false&delivery= +// GetQueryBool("force") == false, true +// GetQueryBool("name") == true, false +// GetQueryBool("delivery") == true, false +func (c *Context) GetQueryBool(key string) (bool, bool) { + if value, ok := c.GetQuery(key); ok { + boolValue, err := strconv.ParseBool(value) + if err != nil { + return true, false + } + return boolValue, true + } + + return true, false +} + // PostForm returns the specified key from a POST urlencoded form or multipart form // when it exists, otherwise it returns an empty string `("")`. func (c *Context) PostForm(key string) (value string) { diff --git a/context_test.go b/context_test.go index 211fbb1b..9dbd187b 100644 --- a/context_test.go +++ b/context_test.go @@ -537,7 +537,7 @@ func TestContextHandler(t *testing.T) { func TestContextQuery(t *testing.T) { c, _ := CreateTestContext(httptest.NewRecorder()) - c.Request, _ = http.NewRequest("GET", "http://example.com/?foo=bar&page=10&id=", nil) + c.Request, _ = http.NewRequest("GET", "http://example.com/?foo=bar&page=10&read=true&id=", nil) value, ok := c.GetQuery("foo") assert.True(t, ok) @@ -568,6 +568,35 @@ func TestContextQuery(t *testing.T) { assert.False(t, ok) assert.Empty(t, value) assert.Empty(t, c.PostForm("foo")) + + valueBool, _ := c.QueryBool("read") + assert.True(t, valueBool) + assert.Equal(t, true, valueBool) + + valueBool, _ = c.QueryBool("id") + assert.False(t, valueBool) + assert.Equal(t, false, valueBool) + + valueBool, ok = c.GetQueryBool("read") + assert.True(t, ok) + assert.True(t, valueBool) + assert.Equal(t, true, valueBool) + assert.Equal(t, true, ok) + + valueBool, ok = c.GetQueryBool("id") + assert.False(t, ok) + assert.True(t, valueBool) + assert.Equal(t, valueBool, true) + assert.Equal(t, ok, false) + + valueBool = c.GetQueryBoolDefault("read", false) + assert.True(t, valueBool) + assert.Equal(t, true, valueBool) + + valueBool = c.GetQueryBoolDefault("id", true) + assert.True(t, valueBool) + assert.Equal(t, true, valueBool) + } func TestContextInitQueryCache(t *testing.T) { diff --git a/docs/doc.md b/docs/doc.md index 8cb53cc2..d42b2b2b 100644 --- a/docs/doc.md +++ b/docs/doc.md @@ -172,12 +172,13 @@ func main() { router := gin.Default() // Query string parameters are parsed using the existing underlying request object. - // The request responds to an url matching: /welcome?firstname=Jane&lastname=Doe + // The request responds to an url matching: /welcome?firstname=Jane&lastname=Doe&want_pizza=true router.GET("/welcome", func(c *gin.Context) { firstname := c.DefaultQuery("firstname", "Guest") lastname := c.Query("lastname") // shortcut for c.Request.URL.Query().Get("lastname") + wantPizza := c.QueryBool("want_pizza") - c.String(http.StatusOK, "Hello %s %s", firstname, lastname) + c.String(http.StatusOK, "%s %s want a pizza? %v", firstname, lastname, wantPizza) }) router.Run(":8080") }