package services import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" ) type CloudflareConfig struct { APIToken string `json:"apiToken"` ZoneID string `json:"zoneId"` } type CloudflareService struct { credentials *CredentialsService } func NewCloudflareService(c *CredentialsService) *CloudflareService { return &CloudflareService{credentials: c} } // PurgeCache clears the entire Cloudflare cache for the configured zone func (s *CloudflareService) PurgeCache(ctx context.Context) error { payload, err := s.credentials.GetDecryptedKey(ctx, "cloudflare_config") if err != nil { return fmt.Errorf("cloudflare credentials missing: %w", err) } var cfg CloudflareConfig if err := json.Unmarshal([]byte(payload), &cfg); err != nil { return fmt.Errorf("invalid cloudflare config: %w", err) } if cfg.APIToken == "" || cfg.ZoneID == "" { return fmt.Errorf("cloudflare not configured") } url := fmt.Sprintf("https://api.cloudflare.com/client/v4/zones/%s/purge_cache", cfg.ZoneID) body := []byte(`{"purge_everything":true}`) req, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(body)) if err != nil { return err } req.Header.Set("Authorization", "Bearer "+cfg.APIToken) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { return fmt.Errorf("cloudflare api request failed: %w", err) } defer resp.Body.Close() if resp.StatusCode != 200 { respBody, _ := io.ReadAll(resp.Body) return fmt.Errorf("cloudflare api returned %d: %s", resp.StatusCode, string(respBody)) } return nil }