Files
kubesphere/pkg/server/params/params.go
KubeSphere CI Bot 447a51f08b feat: kubesphere 4.0 (#6115)
* feat: kubesphere 4.0

Signed-off-by: ci-bot <ci-bot@kubesphere.io>

* feat: kubesphere 4.0

Signed-off-by: ci-bot <ci-bot@kubesphere.io>

---------

Signed-off-by: ci-bot <ci-bot@kubesphere.io>
Co-authored-by: ks-ci-bot <ks-ci-bot@example.com>
Co-authored-by: joyceliu <joyceliu@yunify.com>
2024-09-06 11:05:52 +08:00

127 lines
3.0 KiB
Go

/*
* Please refer to the LICENSE file in the root directory of the project.
* https://github.com/kubesphere/kubesphere/blob/master/LICENSE
*/
package params
import (
"fmt"
"regexp"
"strconv"
"strings"
"github.com/emicklei/go-restful/v3"
)
const (
PagingParam = "paging"
OrderByParam = "orderBy"
ConditionsParam = "conditions"
ReverseParam = "reverse"
)
const (
DefaultLimit = 10
DefaultPage = 1
)
// ParsePaging parse the paging parameters from the request, then returns the limit and offset
// supported format: ?limit=1&page=1
// supported format: ?paging=limit=100,page=1
func ParsePaging(req *restful.Request) (limit, offset int) {
paging := req.QueryParameter(PagingParam)
limit = 10
page := DefaultPage
if paging != "" {
if groups := regexp.MustCompile(`^limit=(-?\d+),page=(\d+)$`).FindStringSubmatch(paging); len(groups) == 3 {
limit = AtoiOrDefault(groups[1], DefaultLimit)
page = AtoiOrDefault(groups[2], DefaultPage)
}
} else {
// try to parse from format ?limit=10&page=1
limit = AtoiOrDefault(req.QueryParameter("limit"), DefaultLimit)
page = AtoiOrDefault(req.QueryParameter("page"), DefaultPage)
}
offset = (page - 1) * limit
// use the explicit offset
if start := req.QueryParameter("start"); start != "" {
offset = AtoiOrDefault(start, offset)
}
return
}
func AtoiOrDefault(str string, defVal int) int {
if result, err := strconv.Atoi(str); err == nil {
return result
}
return defVal
}
var (
invalidKeyRegex = regexp.MustCompile(`[\s(){}\[\]]`)
)
// Ref: stdlib url.ParseQuery
func parseConditions(conditionsStr string) (*Conditions, error) {
// string likes: key1=value1,key2~value2,key3=
// exact query: key=value, if value is empty means label value must be ""
// fuzzy query: key~value, if value is empty means label value is "" or label key not exist
var conditions = &Conditions{Match: make(map[string]string, 0), Fuzzy: make(map[string]string, 0)}
for conditionsStr != "" {
key := conditionsStr
if i := strings.Index(key, ","); i >= 0 {
key, conditionsStr = key[:i], key[i+1:]
} else {
conditionsStr = ""
}
if key == "" {
continue
}
value := ""
var isFuzzy = false
if i := strings.IndexAny(key, "~="); i >= 0 {
if key[i] == '~' {
isFuzzy = true
}
key, value = key[:i], key[i+1:]
}
if invalidKeyRegex.MatchString(key) {
return nil, fmt.Errorf("invalid conditions")
}
if isFuzzy {
conditions.Fuzzy[key] = value
} else {
conditions.Match[key] = value
}
}
return conditions, nil
}
func ParseConditions(req *restful.Request) (*Conditions, error) {
return parseConditions(req.QueryParameter(ConditionsParam))
}
type Conditions struct {
Match map[string]string
Fuzzy map[string]string
}
func GetBoolValueWithDefault(req *restful.Request, name string, dv bool) bool {
reverse := req.QueryParameter(name)
if v, err := strconv.ParseBool(reverse); err == nil {
return v
}
return dv
}
func GetStringValueWithDefault(req *restful.Request, name string, dv string) string {
v := req.QueryParameter(name)
if v == "" {
v = dv
}
return v
}