goyave.dev/goyave/v4@v4.4.11/util/httputil/httputil.go (about) 1 package httputil 2 3 import ( 4 "regexp" 5 "sort" 6 "strconv" 7 "strings" 8 ) 9 10 // HeaderValue represent a value and its quality value (priority) 11 // in a multi-values HTTP header. 12 type HeaderValue struct { 13 Value string 14 Priority float64 15 } 16 17 var multiValuesHeaderRegex *regexp.Regexp 18 19 // ParseMultiValuesHeader parses multi-values HTTP headers, taking the 20 // quality values into account. The result is a slice of values sorted 21 // according to the order of priority. 22 // 23 // See: https://developer.mozilla.org/en-US/docs/Glossary/Quality_values 24 // 25 // For the following header: 26 // 27 // "text/html,text/*;q=0.5,*/*;q=0.7" 28 // 29 // returns 30 // 31 // [{text/html 1} {*/* 0.7} {text/* 0.5}] 32 func ParseMultiValuesHeader(header string) []HeaderValue { 33 if multiValuesHeaderRegex == nil { 34 multiValuesHeaderRegex = regexp.MustCompile(`^q=([01]\.[0-9]{1,3})$`) 35 } 36 split := strings.Split(header, ",") 37 values := make([]HeaderValue, 0, len(split)) 38 39 for _, v := range split { 40 val := HeaderValue{} 41 if i := strings.Index(v, ";"); i != -1 { 42 // Parse priority 43 q := v[i+1:] 44 45 sub := multiValuesHeaderRegex.FindStringSubmatch(q) 46 priority := 0.0 47 if len(sub) > 1 { 48 if p, err := strconv.ParseFloat(sub[1], 64); err == nil { 49 priority = p 50 } 51 } 52 // Priority set to 0 if the quality value cannot be parsed 53 val.Priority = priority 54 55 val.Value = strings.Trim(v[:i], " ") 56 } else { 57 val.Value = strings.Trim(v, " ") 58 val.Priority = 1 59 } 60 61 values = append(values, val) 62 } 63 64 sort.Sort(byPriority(values)) 65 66 return values 67 }