Alexander "PapaTutuWawa
f264bd5604
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
118 lines
2.5 KiB
Go
118 lines
2.5 KiB
Go
package dns
|
|
|
|
import (
|
|
"net"
|
|
"errors"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/patrickmn/go-cache"
|
|
)
|
|
|
|
const (
|
|
// TXT record name that lookupRepoTXT will try to lookup.
|
|
TxtRepoRecord = "_rio-pages."
|
|
|
|
// The key that the TXT record will have to start with, e.g.
|
|
// "repo=some-random-repo".
|
|
TxtRepoKey = "repo="
|
|
|
|
TxtCNAMERecord = "_rio-cname."
|
|
|
|
TxtCNAMEKey = "cname="
|
|
)
|
|
|
|
var (
|
|
// Cache for CNAME resolution results.
|
|
cnameCache = cache.New(1*time.Hour, 1*time.Hour)
|
|
|
|
// Cache for TXT resolution results.
|
|
txtRepoCache = cache.New(1*time.Hour, 1*time.Hour)
|
|
)
|
|
|
|
// Query the domain for the a repository redirect.
|
|
// Returns the new repository name or "", if we could not
|
|
// resolve a repository redirect.
|
|
func LookupRepoTXT(domain string) (string, error) {
|
|
repoLookup, found := txtRepoCache.Get(domain)
|
|
if found {
|
|
return repoLookup.(string), nil
|
|
}
|
|
|
|
txts, err := net.LookupTXT("_rio-pages." + domain)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
repo := ""
|
|
for _, txt := range txts {
|
|
if !strings.HasPrefix(txt, TxtRepoKey) {
|
|
continue
|
|
}
|
|
|
|
repo = strings.TrimPrefix(txt, TxtRepoKey)
|
|
break
|
|
}
|
|
|
|
txtRepoCache.Set(domain, repo, cache.DefaultExpiration)
|
|
return repo, nil
|
|
}
|
|
|
|
// Query the domain for a CNAME record. Returns the resolved
|
|
// CNAME or "", if no CNAME could be queried.
|
|
func LookupCNAME(domain string) (string, error) {
|
|
cname, found := cnameCache.Get(domain)
|
|
if found {
|
|
return cname.(string), nil
|
|
}
|
|
|
|
cname, err := lookupCNAME(domain)
|
|
if err == nil {
|
|
cnameCache.Set(domain, cname, cache.DefaultExpiration)
|
|
return cname.(string), nil
|
|
}
|
|
|
|
altCname, err := lookupCNAMETxt(domain)
|
|
if err == nil {
|
|
cnameCache.Set(domain, altCname, cache.DefaultExpiration)
|
|
return altCname, nil
|
|
}
|
|
|
|
return "", err
|
|
}
|
|
|
|
// Lookup the CNAME by trying to find a CNAME RR. Contrary to net.LookupCNAME,
|
|
// this method fails if we find no CNAME RR.
|
|
func lookupCNAME(domain string) (string, error) {
|
|
query, err := net.LookupCNAME(domain)
|
|
if err == nil {
|
|
if query[len(query)-1] == '.' {
|
|
query = query[:len(query)-1]
|
|
}
|
|
|
|
// Fail if we have no CNAME RR.
|
|
if query == domain {
|
|
return "", errors.New("CNAME is equal to domain")
|
|
}
|
|
|
|
return query, nil
|
|
}
|
|
|
|
return "", err
|
|
}
|
|
|
|
// Performs an alternative CNAME lookup by looking for a special TXT record.
|
|
func lookupCNAMETxt(domain string) (string, error) {
|
|
txts, err := net.LookupTXT(TxtCNAMERecord+domain)
|
|
if err == nil {
|
|
for _, txt := range txts {
|
|
if !strings.HasPrefix(txt, TxtCNAMEKey) {
|
|
continue
|
|
}
|
|
|
|
return strings.TrimPrefix(txt, TxtCNAMEKey), nil
|
|
}
|
|
}
|
|
|
|
return "", err
|
|
} |