Raw
 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}