1package http
2
3import (
4 "errors"
5 "fmt"
6 "net/url"
7 "slices"
8 "strings"
9)
10
11var ErrOrigin = errors.New("http: the origin is not scheme://host[:port] of a served host")
12
13func ParseOrigin(raw, scheme string, hosts ...string) (string, error) {
14 refuse := fmt.Errorf("%w: %q", ErrOrigin, raw)
15 if strings.Contains(raw, "#") {
16 return "", refuse
17 }
18 u, err := url.Parse(raw)
19 if err != nil || u.Scheme != scheme || u.Opaque != "" || u.User != nil || u.Host == "" || u.Path != "" || u.RawPath != "" || u.RawQuery != "" || u.ForceQuery || u.Fragment != "" {
20 return "", refuse
21 }
22 host := CanonicalHost(u.Host)
23 if host != u.Hostname() || !slices.Contains(hosts, host) {
24 return "", refuse
25 }
26 return host, nil
27}