Skip to content

Commit 07bbc65

Browse files
committed
urlchecker with statuscode, bodystring and http method
1 parent 1c6d060 commit 07bbc65

File tree

2 files changed

+85
-18
lines changed

2 files changed

+85
-18
lines changed

url/checker.go

+37-16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package url
22

33
import (
4+
"bytes"
5+
"context"
6+
"io/ioutil"
47
"net/http"
58
"time"
69

@@ -9,13 +12,16 @@ import (
912

1013
// Checker is a checker that check a given URL
1114
type Checker struct {
12-
URL string
13-
Timeout time.Duration
15+
URL string
16+
Timeout time.Duration
17+
Method string // Defaults to GET
18+
ExpectedBodyString string // Disabled if empty
19+
ExpectedStatusCode int // if 0 defaults to 200
1420
}
1521

1622
// NewChecker returns a new url.Checker with the given URL
1723
func NewChecker(url string) Checker {
18-
return Checker{URL: url, Timeout: 5 * time.Second}
24+
return NewCheckerWithTimeout(url, 5*time.Second)
1925
}
2026

2127
// NewCheckerWithTimeout returns a new url.Checker with the given URL and given timeout
@@ -27,31 +33,46 @@ func NewCheckerWithTimeout(url string, timeout time.Duration) Checker {
2733
// If the request returns something different than StatusOK,
2834
// The status is set to StatusBadRequest and the URL is considered Down
2935
func (u Checker) Check() health.Health {
30-
client := http.Client{
31-
Timeout: u.Timeout,
32-
}
33-
36+
ctxWithTimeout, cancelFn := context.WithTimeout(context.Background(), u.Timeout)
37+
defer cancelFn()
3438
health := health.NewHealth()
39+
body := new(bytes.Buffer)
40+
req, err := http.NewRequestWithContext(ctxWithTimeout, u.Method, u.URL, body)
41+
if err != nil {
42+
health.Down().AddInfo("code", http.StatusBadRequest).AddInfo("error", err.Error())
43+
return health
44+
}
3545

36-
resp, err := client.Head(u.URL)
37-
46+
resp, err := http.DefaultClient.Do(req)
3847
if resp != nil {
3948
defer resp.Body.Close()
4049
}
41-
4250
if err != nil {
43-
health.Down().AddInfo("code", http.StatusBadRequest)
44-
51+
health.Down().AddInfo("code", http.StatusBadRequest).AddInfo("error", err.Error())
4552
return health
4653
}
4754

48-
if resp.StatusCode == http.StatusOK {
49-
health.Up()
55+
if u.ExpectedStatusCode == 0 {
56+
u.ExpectedStatusCode = http.StatusOK
57+
}
58+
59+
if resp.StatusCode == u.ExpectedStatusCode {
60+
health.Up().AddInfo("code", resp.StatusCode)
5061
} else {
51-
health.Down()
62+
health.Down().AddInfo("code", resp.StatusCode).AddInfo("expectedCode", u.ExpectedStatusCode)
63+
return health
5264
}
5365

54-
health.AddInfo("code", resp.StatusCode)
66+
if u.ExpectedBodyString != "" {
67+
respbody, err := ioutil.ReadAll(resp.Body)
68+
if err != nil {
69+
health.Down().AddInfo("error", err.Error())
70+
return health
71+
}
72+
if !bytes.ContainsAny(respbody, u.ExpectedBodyString) {
73+
health.Down().AddInfo("body", "does not contain: "+u.ExpectedBodyString)
74+
}
75+
}
5576

5677
return health
5778
}

url/checker_test.go

+48-2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,52 @@ func Test_Checker_Check_Up(t *testing.T) {
4949
check(t, resp, wants, http.StatusOK)
5050
}
5151

52+
func Test_Checker_Check_Up_BodyCheck(t *testing.T) {
53+
mux := http.NewServeMux()
54+
55+
server := httptest.NewServer(mux)
56+
57+
checker := NewChecker(fmt.Sprintf("%s/up/", server.URL))
58+
checker.ExpectedBodyString = "pong"
59+
60+
handler := health.NewHandler()
61+
handler.AddChecker("Up", checker)
62+
63+
mux.Handle("/health/", handler)
64+
mux.HandleFunc("/up/", func(w http.ResponseWriter, r *http.Request) {
65+
fmt.Fprintln(w, "pong")
66+
})
67+
68+
resp, _ := http.Get(fmt.Sprintf("%s/health/", server.URL))
69+
70+
wants := `{"Up":{"code":200,"status":"UP"},"status":"UP"}`
71+
72+
check(t, resp, wants, http.StatusOK)
73+
}
74+
75+
func Test_Checker_Check_Down_BodyCheck(t *testing.T) {
76+
mux := http.NewServeMux()
77+
78+
server := httptest.NewServer(mux)
79+
80+
checker := NewChecker(fmt.Sprintf("%s/up/", server.URL))
81+
checker.ExpectedBodyString = "pong"
82+
83+
handler := health.NewHandler()
84+
handler.AddChecker("Down", checker)
85+
86+
mux.Handle("/health/", handler)
87+
mux.HandleFunc("/up/", func(w http.ResponseWriter, r *http.Request) {
88+
fmt.Fprintln(w, "fail")
89+
})
90+
91+
resp, _ := http.Get(fmt.Sprintf("%s/health/", server.URL))
92+
93+
wants := `{"Down":{"body":"does not contain: pong","code":200,"status":"DOWN"},"status":"DOWN"}`
94+
95+
check(t, resp, wants, http.StatusServiceUnavailable)
96+
}
97+
5298
func Test_Checker_Check_Down(t *testing.T) {
5399
mux := http.NewServeMux()
54100

@@ -67,7 +113,7 @@ func Test_Checker_Check_Down(t *testing.T) {
67113

68114
resp, _ := http.Get(fmt.Sprintf("%s/health/", server.URL))
69115

70-
wants := `{"Down":{"code":500,"status":"DOWN"},"status":"DOWN"}`
116+
wants := `{"Down":{"code":500,"expectedCode":200,"status":"DOWN"},"status":"DOWN"}`
71117

72118
check(t, resp, wants, http.StatusServiceUnavailable)
73119
}
@@ -86,7 +132,7 @@ func Test_Checker_Check_Down_invalid(t *testing.T) {
86132

87133
resp, _ := http.Get(fmt.Sprintf("%s/health/", server.URL))
88134

89-
wants := `{"Down":{"code":400,"status":"DOWN"},"status":"DOWN"}`
135+
wants := `{"Down":{"code":400,"error":"Get : unsupported protocol scheme \"\"","status":"DOWN"},"status":"DOWN"}`
90136
check(t, resp, wants, http.StatusServiceUnavailable)
91137
}
92138

0 commit comments

Comments
 (0)