aboutsummaryrefslogtreecommitdiff
path: root/backend/internal/monitor/checker.go
blob: df386e60bea0383dba835c59da8a83d4f1eb9fad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package monitor

import (
	"context"
	"io"
	"net/http"
	"strings"
	"time"

	"yaum/internal/model"
)

var httpClient = &http.Client{
	Timeout: 10 * time.Second,
	// do NOT set InsecureSkipVerify — we want proper TLS
}

func CheckHTTP(ctx context.Context, url string, keyword string) (model.Heartbeat, *model.SSLInfo) {
	start := time.Now()

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
	if err != nil {
		hb := heartbeatFromError(start, err)
		return hb, nil
	}

	resp, err := httpClient.Do(req)
	elapsed := time.Since(start).Milliseconds()

	if err != nil {
		return model.Heartbeat{
			StatusCode:     0,
			ResponseTimeMs: elapsed,
			IsUp:           false,
			ErrorMessage:   err.Error(),
			TestedAt:       time.Now(),
		}, nil
	}
	defer resp.Body.Close()

	isUp := resp.StatusCode >= 200 && resp.StatusCode < 400
	errMsg := ""

	body, readErr := io.ReadAll(resp.Body)
	if readErr != nil {
		isUp = false
		errMsg = "Erro ao ler corpo: " + readErr.Error()
	} else {
		bodyStr := string(body)

		if keyword != "" && isUp {
			if !strings.Contains(bodyStr, keyword) {
				isUp = false
				errMsg = "Palavra-chave nao encontrada"
			}
		}

		if !isUp {
			snippet := strings.TrimSpace(bodyStr)
			if len(snippet) > 300 {
				snippet = snippet[:300]
			}
			if errMsg == "" {
				errMsg = snippet
			} else {
				errMsg += " | " + snippet
			}
		}
	}

	hb := model.Heartbeat{
		StatusCode:     resp.StatusCode,
		ResponseTimeMs: elapsed,
		IsUp:           isUp,
		ErrorMessage:   errMsg,
		TestedAt:       time.Now(),
	}

	// Extract TLS certificate info
	var ssl *model.SSLInfo
	if resp.TLS != nil && len(resp.TLS.PeerCertificates) > 0 {
		cert := resp.TLS.PeerCertificates[0]
		days := int(time.Until(cert.NotAfter).Hours() / 24)
		ssl = &model.SSLInfo{
			ServiceID:     0, // filled in by caller
			Issuer:        cert.Issuer.CommonName,
			ExpiresAt:     cert.NotAfter,
			DaysRemaining: days,
			CheckedAt:     time.Now(),
		}
	}

	return hb, ssl
}

func heartbeatFromError(start time.Time, err error) model.Heartbeat {
	return model.Heartbeat{
		StatusCode:     0,
		ResponseTimeMs: time.Since(start).Milliseconds(),
		IsUp:           false,
		ErrorMessage:   err.Error(),
		TestedAt:       time.Now(),
	}
}