feat(core): improve CNAME binding logic with CAS and update hostname validation
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user