watcher.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package watcher
  2. import (
  3. "crypto/tls"
  4. "fmt"
  5. "github.com/SongZihuan/web-watcher/src/config"
  6. "github.com/SongZihuan/web-watcher/src/logger"
  7. "github.com/SongZihuan/web-watcher/src/notify"
  8. "io"
  9. "net/http"
  10. "strings"
  11. )
  12. func Run() error {
  13. if !config.IsReady() {
  14. panic("config is not ready")
  15. }
  16. for _, url := range config.GetConfig().Watcher.URLs {
  17. logger.Infof("开始请求 %s", url.Name)
  18. _, err := httpProcessRetry(url.URL, url.Name, url.Status, url.ClientKeyPair, url.SkipTLSVerify.IsEnable(false))
  19. if err != nil {
  20. logger.Errorf("请求 %s 出现异常:%s", url.Name, err.Error())
  21. notify.NewRecord(url.Name, url.URL, err.Error())
  22. }
  23. logger.Infof("处理 %s 完成", url.Name)
  24. }
  25. notify.SendNotify()
  26. return nil
  27. }
  28. func httpProcessRetry(url string, name string, statusList []string, cert *tls.Certificate, skipTLSVerify bool) (int, error) {
  29. var err1, err2, err3 error
  30. var statusCode int
  31. statusCode, err1 = httpProcessGet(url, name, statusList, cert, skipTLSVerify)
  32. if err1 == nil {
  33. return statusCode, nil
  34. }
  35. statusCode, err2 = httpProcessGet(url, name, statusList, cert, skipTLSVerify)
  36. if err2 == nil {
  37. return statusCode, nil
  38. }
  39. statusCode, err3 = httpProcessGet(url, name, statusList, cert, skipTLSVerify)
  40. if err3 == nil {
  41. return statusCode, nil
  42. }
  43. // 去除重复
  44. var errMap = make(map[string]bool, 3)
  45. errMap[err1.Error()] = true
  46. errMap[err2.Error()] = true
  47. errMap[err3.Error()] = true
  48. var errStrBuilder strings.Builder
  49. var n = 0
  50. for err, _ := range errMap {
  51. n += 1
  52. errStrBuilder.WriteString(fmt.Sprintf("检查 %s 错误[%d]: %s; ", name, n, err))
  53. }
  54. err := fmt.Errorf("%s", strings.TrimSpace(errStrBuilder.String()))
  55. return -1, err
  56. }
  57. func httpProcessGet(url string, name string, statusList []string, cert *tls.Certificate, skipTLSVerify bool) (int, error) {
  58. // 创建一个自定义的Transport,这样我们可以访问TLS连接状态
  59. tc := &tls.Config{InsecureSkipVerify: skipTLSVerify}
  60. if cert != nil {
  61. tc.Certificates = []tls.Certificate{*cert}
  62. }
  63. tr := &http.Transport{
  64. TLSClientConfig: tc, // 忽略服务器证书验证
  65. }
  66. // 使用自定义的Transport创建一个HTTP客户端
  67. client := &http.Client{Transport: tr}
  68. // 发送请求
  69. fmt.Printf("请求URL:%s\n", url)
  70. resp, err := client.Get(url)
  71. if err != nil {
  72. return 0, fmt.Errorf("获取 GET %s 请求错误:%s", name, err.Error())
  73. }
  74. defer func() {
  75. _ = resp.Body.Close()
  76. }()
  77. statusCode := resp.StatusCode
  78. data, err := io.ReadAll(resp.Body)
  79. if err != nil {
  80. return statusCode, err
  81. }
  82. fmt.Printf("statusCode: %d\n%s\n", statusCode, string(data))
  83. for _, s := range statusList {
  84. switch s {
  85. case "xxx":
  86. return statusCode, nil
  87. case "1xx":
  88. if statusCode >= 100 && statusCode <= 199 {
  89. return statusCode, nil
  90. }
  91. case "2xx":
  92. if statusCode >= 200 && statusCode <= 299 {
  93. return statusCode, nil
  94. }
  95. case "3xx":
  96. if statusCode >= 300 && statusCode <= 399 {
  97. return statusCode, nil
  98. }
  99. case "4xx":
  100. if statusCode >= 400 && statusCode <= 499 {
  101. return statusCode, nil
  102. }
  103. case "5xx":
  104. if statusCode >= 500 && statusCode <= 599 {
  105. return statusCode, nil
  106. }
  107. default:
  108. status := fmt.Sprintf("%d", statusCode)
  109. if status == s {
  110. return statusCode, nil
  111. }
  112. }
  113. }
  114. return statusCode, fmt.Errorf("检查 GET %s 状态码错误: %d", name, statusCode)
  115. }