73 lines
1.9 KiB
Go
73 lines
1.9 KiB
Go
package config
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"net/url"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Resolve turns a short topic, host/topic, or absolute URL into an origin and
|
||
|
|
// a single topic name. defaultHost is used only for short names.
|
||
|
|
func Resolve(topic, defaultHost string) (origin, name string, err error) {
|
||
|
|
topic = strings.TrimSpace(topic)
|
||
|
|
if topic == "" {
|
||
|
|
return "", "", fmt.Errorf("empty topic")
|
||
|
|
}
|
||
|
|
if !strings.Contains(topic, "://") && strings.Contains(topic, "/") {
|
||
|
|
return Resolve("https://"+topic, "")
|
||
|
|
}
|
||
|
|
if strings.Contains(topic, "://") {
|
||
|
|
u, err := url.Parse(topic)
|
||
|
|
if err != nil || u.Host == "" || (u.Scheme != "https" && u.Scheme != "http") {
|
||
|
|
return "", "", fmt.Errorf("invalid topic URL %q", topic)
|
||
|
|
}
|
||
|
|
path := strings.Trim(u.Path, "/")
|
||
|
|
if path == "" {
|
||
|
|
return "", "", fmt.Errorf("topic URL %q has no topic", topic)
|
||
|
|
}
|
||
|
|
base := u.Scheme + "://" + u.Host
|
||
|
|
if i := strings.LastIndex(path, "/"); i >= 0 {
|
||
|
|
base += "/" + path[:i]
|
||
|
|
path = path[i+1:]
|
||
|
|
}
|
||
|
|
if err := checkName(path); err != nil {
|
||
|
|
return "", "", err
|
||
|
|
}
|
||
|
|
return base, path, nil
|
||
|
|
}
|
||
|
|
if err := checkName(topic); err != nil {
|
||
|
|
return "", "", err
|
||
|
|
}
|
||
|
|
origin, err = normalizeOrigin(defaultHost)
|
||
|
|
if err != nil {
|
||
|
|
return "", "", fmt.Errorf("topic %q: %w", topic, err)
|
||
|
|
}
|
||
|
|
return origin, topic, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func checkName(name string) error {
|
||
|
|
if name == "" || strings.Contains(name, ",") || strings.ContainsAny(name, " \t") {
|
||
|
|
return fmt.Errorf("invalid topic name %q", name)
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func normalizeOrigin(host string) (string, error) {
|
||
|
|
host = strings.TrimSpace(host)
|
||
|
|
if host == "" {
|
||
|
|
return "", fmt.Errorf("no default-host")
|
||
|
|
}
|
||
|
|
if !strings.Contains(host, "://") {
|
||
|
|
host = "https://" + host
|
||
|
|
}
|
||
|
|
u, err := url.Parse(strings.TrimRight(host, "/"))
|
||
|
|
if err != nil || u.Host == "" || (u.Scheme != "https" && u.Scheme != "http") {
|
||
|
|
return "", fmt.Errorf("invalid host %q", host)
|
||
|
|
}
|
||
|
|
origin := u.Scheme + "://" + u.Host
|
||
|
|
if path := strings.Trim(u.Path, "/"); path != "" {
|
||
|
|
origin += "/" + path
|
||
|
|
}
|
||
|
|
return origin, nil
|
||
|
|
}
|