~ knotless Search/
↑↓ move↵ open⇧↵ all results
0
0
main
78 lines · 1.9 KB Raw History
package guestnet

import (
	"cmp"
	"fmt"
	"net/url"
	"regexp"
	"strings"
)

const (
	EventsPath = "/v1/events"

	RelayHost = "relay.localhost"
)

var (
	bundleOnNetworkURL = regexp.MustCompile(`"guest_onnetwork_url"\s*:\s*"([^"]+)"`)

	relayAddress = regexp.MustCompile(`(\d+\.\d+\.\d+\.\d+)\s+relay\.localhost`)
)

type RelayTarget struct {
	URL string

	Resolve string
}

func GuestOnNetworkURL(ingressURL string) (string, error) {
	trimmed := strings.TrimRight(strings.TrimSpace(ingressURL), "/")
	if trimmed == "" {
		return "", fmt.Errorf("guestnet: no ingress URL")
	}
	u, err := url.Parse(trimmed)
	if err != nil || u.Host == "" || (u.Scheme != "https" && u.Scheme != "http") {
		return "", fmt.Errorf("guestnet: ingress URL %q is not an absolute http or https URL", ingressURL)
	}
	if u.User != nil || u.RawQuery != "" || u.Fragment != "" {
		return "", fmt.Errorf("guestnet: ingress URL %q carries a user, query or fragment", ingressURL)
	}
	return trimmed + EventsPath, nil
}

func OnNetworkURLFromBundle(userData, fallback string) string {
	if m := bundleOnNetworkURL.FindStringSubmatch(userData); m != nil {
		return m[1]
	}
	url, err := GuestOnNetworkURL(fallback)
	if err != nil {
		return ""
	}
	return url
}

func RelayTargets(userData, fallback string) []RelayTarget {
	target := OnNetworkURLFromBundle(userData, fallback)
	targets := []RelayTarget{{URL: target}}
	address, ok := RequesterRelayAddress(userData)
	if !ok || target == "" {
		return targets
	}
	u, err := url.Parse(target)
	if err != nil || !strings.HasSuffix(u.Hostname(), "."+RelayHost) {
		return targets
	}
	port := u.Port()
	port = cmp.Or(port, "80")
	targets = append(targets, RelayTarget{URL: target, Resolve: u.Hostname() + ":" + port + ":" + address})
	return targets
}

func RequesterRelayAddress(userData string) (string, bool) {
	m := relayAddress.FindStringSubmatch(userData)
	if m == nil {
		return "", false
	}
	return m[1], true
}