pages-server/server/domains.go

111 lines
3.6 KiB
Go
Raw Normal View History

2021-12-05 13:45:17 +00:00
package server
2021-03-16 23:34:31 +00:00
import (
"net"
"strings"
"time"
2021-12-05 13:47:33 +00:00
"github.com/valyala/fasthttp"
2021-12-05 14:02:44 +00:00
"codeberg.org/codeberg/pages/server/cache"
2021-12-05 13:47:33 +00:00
"codeberg.org/codeberg/pages/server/upstream"
)
// DnsLookupCacheTimeout specifies the timeout for the DNS lookup cache.
2021-11-25 15:12:28 +00:00
var DnsLookupCacheTimeout = 15 * time.Minute
// getTargetFromDNS searches for CNAME or TXT entries on the request domain ending with MainDomainSuffix.
// If everything is fine, it returns the target data.
2021-12-05 14:02:44 +00:00
func getTargetFromDNS(domain, mainDomainSuffix string, dnsLookupCache cache.SetGetKey) (targetOwner, targetRepo, targetBranch string) {
// Get CNAME or TXT
var cname string
var err error
if cachedName, ok := dnsLookupCache.Get(domain); ok {
cname = cachedName.(string)
} else {
cname, err = net.LookupCNAME(domain)
cname = strings.TrimSuffix(cname, ".")
2021-12-05 13:45:17 +00:00
if err != nil || !strings.HasSuffix(cname, mainDomainSuffix) {
cname = ""
2021-07-13 08:28:06 +00:00
// TODO: check if the A record matches!
names, err := net.LookupTXT(domain)
if err == nil {
for _, name := range names {
name = strings.TrimSuffix(name, ".")
2021-12-05 13:45:17 +00:00
if strings.HasSuffix(name, mainDomainSuffix) {
cname = name
break
}
}
}
}
_ = dnsLookupCache.Set(domain, cname, DnsLookupCacheTimeout)
}
if cname == "" {
return
}
2021-12-05 13:45:17 +00:00
cnameParts := strings.Split(strings.TrimSuffix(cname, mainDomainSuffix), ".")
targetOwner = cnameParts[len(cnameParts)-1]
if len(cnameParts) > 1 {
targetRepo = cnameParts[len(cnameParts)-2]
}
if len(cnameParts) > 2 {
targetBranch = cnameParts[len(cnameParts)-3]
}
if targetRepo == "" {
targetRepo = "pages"
}
if targetBranch == "" && targetRepo != "pages" {
targetBranch = "pages"
}
// if targetBranch is still empty, the caller must find the default branch
2021-03-16 23:34:31 +00:00
return
}
2021-03-19 12:20:00 +00:00
// CanonicalDomainCacheTimeout specifies the timeout for the canonical domain cache.
2021-11-25 15:12:28 +00:00
var CanonicalDomainCacheTimeout = 15 * time.Minute
// checkCanonicalDomain returns the canonical domain specified in the repo (using the file `.canonical-domain`).
2021-12-05 14:02:44 +00:00
func checkCanonicalDomain(targetOwner, targetRepo, targetBranch, actualDomain, mainDomainSuffix, giteaRoot, giteaApiToken string, canonicalDomainCache cache.SetGetKey) (canonicalDomain string, valid bool) {
domains := []string{}
2021-07-13 08:28:06 +00:00
if cachedValue, ok := canonicalDomainCache.Get(targetOwner + "/" + targetRepo + "/" + targetBranch); ok {
domains = cachedValue.([]string)
for _, domain := range domains {
if domain == actualDomain {
valid = true
break
}
}
} else {
2021-07-13 08:28:06 +00:00
req := fasthttp.AcquireRequest()
2021-12-05 13:45:17 +00:00
req.SetRequestURI(giteaRoot + "/api/v1/repos/" + targetOwner + "/" + targetRepo + "/raw/" + targetBranch + "/.domains" + "?access_token=" + giteaApiToken)
2021-07-13 08:28:06 +00:00
res := fasthttp.AcquireResponse()
2021-12-05 13:47:33 +00:00
err := upstream.Client.Do(req, res)
if err == nil && res.StatusCode() == fasthttp.StatusOK {
for _, domain := range strings.Split(string(res.Body()), "\n") {
domain = strings.ToLower(domain)
domain = strings.TrimSpace(domain)
domain = strings.TrimPrefix(domain, "http://")
domain = strings.TrimPrefix(domain, "https://")
if len(domain) > 0 && !strings.HasPrefix(domain, "#") && !strings.ContainsAny(domain, "\t /") && strings.ContainsRune(domain, '.') {
domains = append(domains, domain)
}
if domain == actualDomain {
valid = true
}
}
}
2021-12-05 13:45:17 +00:00
domains = append(domains, targetOwner+mainDomainSuffix)
2021-11-25 15:12:28 +00:00
if domains[len(domains)-1] == actualDomain {
valid = true
}
if targetRepo != "" && targetRepo != "pages" {
2021-11-25 15:12:28 +00:00
domains[len(domains)-1] += "/" + targetRepo
}
2021-11-25 15:12:28 +00:00
_ = canonicalDomainCache.Set(targetOwner+"/"+targetRepo+"/"+targetBranch, domains, CanonicalDomainCacheTimeout)
}
canonicalDomain = domains[0]
return
}