proxy_checker.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package config
  2. import (
  3. "context"
  4. "fmt"
  5. "log"
  6. "net/http"
  7. "strings"
  8. "sync"
  9. "time"
  10. )
  11. const (
  12. proxyCheckTimeout = 10 * time.Second
  13. testImagePath = "/img-original/img/2024/01/21/20/50/51/115365120_p0.jpg"
  14. )
  15. var (
  16. workingProxies []string
  17. workingProxiesMutex sync.RWMutex
  18. stopChan chan struct{}
  19. )
  20. func InitializeProxyChecker(r context.Context) {
  21. stopChan = make(chan struct{})
  22. StartProxyChecker(r)
  23. }
  24. func StartProxyChecker(r context.Context) {
  25. go func() {
  26. for {
  27. select {
  28. case <-stopChan:
  29. log.Print("Stopping proxy checker...")
  30. return
  31. default:
  32. checkProxies(r)
  33. if t := GlobalConfig.ProxyCheckInterval; t > 0 {
  34. time.Sleep(t)
  35. } else {
  36. log.Print("Proxy check interval set to 0, disabling auto-check from now on.")
  37. select {} // Sweet dreams!
  38. }
  39. }
  40. }
  41. }()
  42. }
  43. func StopProxyChecker() {
  44. close(stopChan)
  45. }
  46. func checkProxies(r context.Context) {
  47. logln("Starting proxy check...")
  48. var wg sync.WaitGroup
  49. var mutex sync.Mutex
  50. var newWorkingProxies []string
  51. logf("Total proxies to check: %d", len(BuiltinProxyList))
  52. for _, proxy := range BuiltinProxyList {
  53. wg.Add(1)
  54. go func(proxyURL string) {
  55. defer wg.Done()
  56. isWorking, resp := testProxy(r, proxyURL)
  57. status := ""
  58. if resp != nil {
  59. status = resp.Status
  60. }
  61. if isWorking {
  62. mutex.Lock()
  63. newWorkingProxies = append(newWorkingProxies, proxyURL)
  64. mutex.Unlock()
  65. logf("[OK] %s %s", proxyURL, status)
  66. } else {
  67. logf("[ERR] %s %s", proxyURL, status)
  68. }
  69. }(proxy)
  70. }
  71. wg.Wait()
  72. updateWorkingProxies(newWorkingProxies)
  73. }
  74. func testProxy(r context.Context, proxyBaseURL string) (bool, *http.Response) {
  75. client := &http.Client{Timeout: proxyCheckTimeout}
  76. fullURL := fmt.Sprintf("%s%s", strings.TrimRight(proxyBaseURL, "/"), testImagePath)
  77. logf("Testing proxy %s with full URL: %s", proxyBaseURL, fullURL)
  78. req, err := http.NewRequestWithContext(r, "GET", fullURL, nil)
  79. if err != nil {
  80. logf("Error creating request for proxy %s: %v", proxyBaseURL, err)
  81. return false, nil
  82. }
  83. resp, err := client.Do(req)
  84. if err != nil {
  85. logf("Error testing proxy %s: %v", proxyBaseURL, err)
  86. return false, nil
  87. }
  88. defer resp.Body.Close()
  89. return resp.StatusCode == http.StatusOK, resp
  90. }
  91. func updateWorkingProxies(newProxies []string) {
  92. workingProxiesMutex.Lock()
  93. defer workingProxiesMutex.Unlock()
  94. workingProxies = newProxies
  95. logf("Updated working proxies. Count: %d", len(workingProxies))
  96. }
  97. func GetWorkingProxies() []string {
  98. workingProxiesMutex.RLock()
  99. defer workingProxiesMutex.RUnlock()
  100. return append([]string{}, workingProxies...)
  101. }
  102. // Helper functions for logging
  103. func logf(format string, v ...any) {
  104. log.Printf(format, v...)
  105. }
  106. func logln(v ...any) {
  107. log.Print(v...)
  108. }