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  }