package entity import ( "encoding/json" "net/url" "sort" "strings" ) type UrlValue map[string]string func QueryToMap(query string) (result UrlValue) { result = UrlValue{} var value url.Values fUrl, _ := url.Parse(query) if fUrl.Scheme == "" { q, _ := url.ParseQuery(query) value = q } else { value = fUrl.Query() } for k, v := range value { result[k] = v[0] } return result } func (value *UrlValue) Reader() *strings.Reader { b, _ := json.Marshal(value) return strings.NewReader(string(b)) } func (value *UrlValue) Body() *strings.Reader { return strings.NewReader(value.Encode()) } func (value UrlValue) JsonString() string { b, _ := json.Marshal(value) return string(b) } func (value *UrlValue) Encode() string { values := url.Values{} for k, v := range *value { values.Set(k, v) } return values.Encode() } func (value UrlValue) Query() string { var buf strings.Builder keys := make([]string, 0, len(value)) for k := range value { keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { v := value[k] if buf.Len() > 0 { buf.WriteByte('&') } buf.WriteString(k) buf.WriteByte('=') buf.WriteString(v) } return buf.String() } func UrlMergeQuery(rawUrl, query string) string { q, _ := url.Parse(rawUrl) rawKeys, rawValues := parseQuery(q.RawQuery) keys, values := parseQuery(query) for idx, k := range keys { value := values[idx] cidx := containsIndex(rawKeys, k) if cidx == -1 { rawKeys = append(rawKeys, k) rawValues = append(rawValues, value) } else { rawValues[cidx] = value } } rawQuery := []string{} for idx, key := range rawKeys { rawQuery = append(rawQuery, key+"="+rawValues[idx]) } q.RawQuery = strings.Join(rawQuery, "&") return q.String() } func parseQuery(query string) (keys, values []string) { for query != "" { key := query if i := strings.IndexAny(key, "&;"); i >= 0 { key, query = key[:i], key[i+1:] } else { query = "" } if key == "" { continue } value := "" if i := strings.Index(key, "="); i >= 0 { key, value = key[:i], key[i+1:] } keys = append(keys, key) values = append(values, value) } return } func containsIndex(list []string, elem string) int { for idx, v := range list { if elem == v { return idx } } return -1 }