feat(core): improve CNAME binding logic with CAS and update hostname validation

This commit is contained in:
ExplodingDragon
2026-02-01 00:49:08 +08:00
parent b4c0ae11df
commit 57e07b3825
7 changed files with 123 additions and 16 deletions

View File

@@ -35,16 +35,50 @@ func (a *DomainAlias) Query(ctx context.Context, domain string) (*Alias, error)
}
func (a *DomainAlias) Bind(ctx context.Context, domains []string, owner, repo string) error {
oldDomains := make([]string, 0)
rKey := base64.URLEncoding.EncodeToString([]byte(fmt.Sprintf("%s/%s", owner, repo)))
if oldStr, err := a.config.Get(ctx, rKey); err == nil {
_ = json.Unmarshal([]byte(oldStr), &oldDomains)
}
for _, oldDomain := range oldDomains {
if err := a.Unbind(ctx, oldDomain); err != nil {
var oldDomains []string
domainsRaw, _ := json.Marshal(domains)
for {
success, err := a.config.PutIfNotExists(ctx, rKey, string(domainsRaw), kv.TTLKeep)
if err != nil {
return err
}
if success {
oldDomains = []string{}
break
}
oldStr, err := a.config.Get(ctx, rKey)
if err != nil {
continue
}
if err = json.Unmarshal([]byte(oldStr), &oldDomains); err != nil {
oldDomains = []string{}
}
success, err = a.config.CompareAndSwap(ctx, rKey, oldStr, string(domainsRaw))
if err != nil {
return err
}
if success {
break
}
}
newDomainsMap := make(map[string]bool)
for _, d := range domains {
newDomainsMap[d] = true
}
for _, oldDomain := range oldDomains {
if !newDomainsMap[oldDomain] {
_ = a.Unbind(ctx, oldDomain)
}
}
if len(domains) == 0 {
return nil
}
@@ -53,12 +87,8 @@ func (a *DomainAlias) Bind(ctx context.Context, domains []string, owner, repo st
Repo: repo,
}
aliasMetaRaw, _ := json.Marshal(aliasMeta)
domainsRaw, _ := json.Marshal(domains)
_ = a.config.Put(ctx, rKey, string(domainsRaw), kv.TTLKeep)
for _, domain := range domains {
if err := a.config.Put(ctx, domain, string(aliasMetaRaw), kv.TTLKeep); err != nil {
return err
}
_ = a.config.Put(ctx, domain, string(aliasMetaRaw), kv.TTLKeep)
}
return nil
}

View File

@@ -201,7 +201,7 @@ func (s *ServerMeta) parsePageConfig(ctx context.Context, meta *PageMetaContent,
cname, err := vfs.ReadString(ctx, "CNAME")
if cname != "" && err == nil {
cname = strings.TrimSpace(cname)
if al, ok := s.aliasCheck(cname); ok {
if al, ok := s.AliasCheck(cname); ok {
alias = append(alias, al)
} else {
return fmt.Errorf("invalid alias %s", cname)
@@ -233,7 +233,7 @@ func (s *ServerMeta) parsePageConfig(ctx context.Context, meta *PageMetaContent,
if item == "" {
continue
}
if al, ok := s.aliasCheck(item); ok {
if al, ok := s.AliasCheck(item); ok {
alias = append(alias, al)
} else {
return fmt.Errorf("invalid alias %s", item)
@@ -269,9 +269,9 @@ func (s *ServerMeta) parsePageConfig(ctx context.Context, meta *PageMetaContent,
return nil
}
var regexpHostname = regexp.MustCompile(`^(?:([a-z0-9-]+|\*)\.)?([a-z0-9-]{1,61})\.([a-z0-9]{2,7})$`)
var regexpHostname = regexp.MustCompile(`^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,18}$`)
func (s *ServerMeta) aliasCheck(cname string) (string, bool) {
func (s *ServerMeta) AliasCheck(cname string) (string, bool) {
cname = strings.TrimSpace(cname)
if !regexpHostname.MatchString(cname) {
return "", false