package cloudflare import ( "bytes" "encoding/json" "errors" "fmt" "io" "net/http" "time" "github.com/cloudflare/cloudflare-go" ) type Cloudflare struct { Zone string `json:"zone" yaml:"zone"` RecordId string `json:"record_id" yaml:"record_id"` Token string `json:"token" yaml:"token"` Email string `json:"email" yaml:"email"` } type DnsProvider struct { Api *cloudflare.API TTL int ZoneResource *cloudflare.ResourceContainer Cloudflare } func New(ttl int, conf Cloudflare, Http *http.Client) (*DnsProvider, error) { var p = DnsProvider{ TTL: ttl, Cloudflare: conf, } if p.Zone == "" { return nil, errors.New("cloudflare zone 不能为空") } if p.Token == "" { return nil, errors.New("cloudflare token 不能为空") } p.ZoneResource = cloudflare.ZoneIdentifier(p.Zone) var err error p.Api, err = cloudflare.NewWithAPIToken(p.Token, cloudflare.HTTPClient(Http)) return &p, err } func (a DnsProvider) SetDomainRecord(domain, ip string) error { url := fmt.Sprintf("https://api.cloudflare.com/client/v4/zones/%s/dns_records/%s", a.Zone, a.RecordId) proxied := false payload := cloudflare.DNSRecord{ Type: "A", Name: domain, Content: ip, TTL: a.TTL, Proxied: &proxied, Comment: "DDNS for " + domain, } jsonPayload, err := json.Marshal(payload) if err != nil { return err } // Make the HTTP GET request req, err := http.NewRequest("PUT", url, bytes.NewBuffer(jsonPayload)) if err != nil { return err } req.Header.Set("X-Auth-Email", a.Email) req.Header.Set("X-Auth-Key", a.Token) time.Sleep(time.Millisecond * 200) // avoid request too fast after login client := &http.Client{} resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { return err } fmt.Println(string(body), resp.Status) return nil }