package altsvc
import (
"fmt"
"strconv"
"strings"
)
type Service struct {
Clear bool ProtocolID string AltAuthority AltAuthority
MaxAge int
Persist int
}
type AltAuthority struct {
Host string Port string
}
func Parse(s string) ([]Service, error) {
ret := make([]Service, 0)
if s == "clear" {
ret = append(ret, Service{Clear: true})
return ret, nil
}
services := strings.Split(s, ",")
for i, svcString := range services {
var svc Service
params := strings.Split(svcString, ";")
for j, kv := range params {
rawKV := strings.TrimSpace(kv)
k, v, ok := strings.Cut(rawKV, "=")
if !ok {
if rawKV == "" && j > 0 && j == len(params)-1 && i == len(services)-1 {
break
}
return nil, fmt.Errorf("invalid parameter: %s", kv)
}
switch k {
case "ma":
ma, err := strconv.Atoi(v)
if err != nil {
return nil, fmt.Errorf("invalid value of 'ma': %s", v)
}
svc.MaxAge = ma
case "persist":
persist, err := strconv.Atoi(v)
if err != nil {
return nil, fmt.Errorf("invalid value of 'persist': %s", v)
}
if persist != 1 {
continue
}
svc.Persist = 1
default:
rawValue, err := strconv.Unquote(v)
if err != nil {
return nil, fmt.Errorf("cannot unquote the value of 'alt-authority': %s", v)
}
h, p, ok := strings.Cut(rawValue, ":")
if !ok {
return nil, fmt.Errorf("invalid value of 'alt-authority': %s", v)
}
svc.ProtocolID = k
svc.AltAuthority.Host = h
svc.AltAuthority.Port = p
}
}
ret = append(ret, svc)
}
return ret, nil
}