mirror of
https://github.com/TwiN/gatus.git
synced 2024-12-22 14:41:01 +01:00
fix: Print response body on failure if debug is set to true
This commit is contained in:
parent
f8f61deb2c
commit
038c8c8d8e
@ -33,7 +33,7 @@ const (
|
||||
// Values that could replace the placeholder: 1, 500, 1000, ...
|
||||
ResponseTimePlaceholder = "[RESPONSE_TIME]"
|
||||
|
||||
// BodyPlaceholder is a placeholder for the body of the response
|
||||
// BodyPlaceholder is a placeholder for the Body of the response
|
||||
//
|
||||
// Values that could replace the placeholder: {}, {"data":{"name":"john"}}, ...
|
||||
BodyPlaceholder = "[BODY]"
|
||||
@ -232,7 +232,7 @@ func isEqual(first, second string) bool {
|
||||
func sanitizeAndResolve(elements []string, result *Result) ([]string, []string) {
|
||||
parameters := make([]string, len(elements))
|
||||
resolvedParameters := make([]string, len(elements))
|
||||
body := strings.TrimSpace(string(result.body))
|
||||
body := strings.TrimSpace(string(result.Body))
|
||||
for i, element := range elements {
|
||||
element = strings.TrimSpace(element)
|
||||
parameters[i] = element
|
||||
@ -266,7 +266,7 @@ func sanitizeAndResolve(elements []string, result *Result) ([]string, []string)
|
||||
checkingForExistence = true
|
||||
element = strings.TrimSuffix(strings.TrimPrefix(element, HasFunctionPrefix), FunctionSuffix)
|
||||
}
|
||||
resolvedElement, resolvedElementLength, err := jsonpath.Eval(strings.TrimPrefix(strings.TrimPrefix(element, BodyPlaceholder), "."), result.body)
|
||||
resolvedElement, resolvedElementLength, err := jsonpath.Eval(strings.TrimPrefix(strings.TrimPrefix(element, BodyPlaceholder), "."), result.Body)
|
||||
if checkingForExistence {
|
||||
if err != nil {
|
||||
element = "false"
|
||||
|
@ -5,7 +5,7 @@ import "testing"
|
||||
func BenchmarkCondition_evaluateWithBodyStringAny(b *testing.B) {
|
||||
condition := Condition("[BODY].name == any(john.doe, jane.doe)")
|
||||
for n := 0; n < b.N; n++ {
|
||||
result := &Result{body: []byte("{\"name\": \"john.doe\"}")}
|
||||
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
||||
condition.evaluate(result, false)
|
||||
}
|
||||
b.ReportAllocs()
|
||||
@ -14,7 +14,7 @@ func BenchmarkCondition_evaluateWithBodyStringAny(b *testing.B) {
|
||||
func BenchmarkCondition_evaluateWithBodyStringAnyFailure(b *testing.B) {
|
||||
condition := Condition("[BODY].name == any(john.doe, jane.doe)")
|
||||
for n := 0; n < b.N; n++ {
|
||||
result := &Result{body: []byte("{\"name\": \"bob.doe\"}")}
|
||||
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
||||
condition.evaluate(result, false)
|
||||
}
|
||||
b.ReportAllocs()
|
||||
@ -23,7 +23,7 @@ func BenchmarkCondition_evaluateWithBodyStringAnyFailure(b *testing.B) {
|
||||
func BenchmarkCondition_evaluateWithBodyString(b *testing.B) {
|
||||
condition := Condition("[BODY].name == john.doe")
|
||||
for n := 0; n < b.N; n++ {
|
||||
result := &Result{body: []byte("{\"name\": \"john.doe\"}")}
|
||||
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
||||
condition.evaluate(result, false)
|
||||
}
|
||||
b.ReportAllocs()
|
||||
@ -32,7 +32,7 @@ func BenchmarkCondition_evaluateWithBodyString(b *testing.B) {
|
||||
func BenchmarkCondition_evaluateWithBodyStringFailure(b *testing.B) {
|
||||
condition := Condition("[BODY].name == john.doe")
|
||||
for n := 0; n < b.N; n++ {
|
||||
result := &Result{body: []byte("{\"name\": \"bob.doe\"}")}
|
||||
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
||||
condition.evaluate(result, false)
|
||||
}
|
||||
b.ReportAllocs()
|
||||
@ -41,7 +41,7 @@ func BenchmarkCondition_evaluateWithBodyStringFailure(b *testing.B) {
|
||||
func BenchmarkCondition_evaluateWithBodyStringFailureInvalidPath(b *testing.B) {
|
||||
condition := Condition("[BODY].user.name == bob.doe")
|
||||
for n := 0; n < b.N; n++ {
|
||||
result := &Result{body: []byte("{\"name\": \"bob.doe\"}")}
|
||||
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
||||
condition.evaluate(result, false)
|
||||
}
|
||||
b.ReportAllocs()
|
||||
@ -50,7 +50,7 @@ func BenchmarkCondition_evaluateWithBodyStringFailureInvalidPath(b *testing.B) {
|
||||
func BenchmarkCondition_evaluateWithBodyStringLen(b *testing.B) {
|
||||
condition := Condition("len([BODY].name) == 8")
|
||||
for n := 0; n < b.N; n++ {
|
||||
result := &Result{body: []byte("{\"name\": \"john.doe\"}")}
|
||||
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
||||
condition.evaluate(result, false)
|
||||
}
|
||||
b.ReportAllocs()
|
||||
@ -59,7 +59,7 @@ func BenchmarkCondition_evaluateWithBodyStringLen(b *testing.B) {
|
||||
func BenchmarkCondition_evaluateWithBodyStringLenFailure(b *testing.B) {
|
||||
condition := Condition("len([BODY].name) == 8")
|
||||
for n := 0; n < b.N; n++ {
|
||||
result := &Result{body: []byte("{\"name\": \"bob.doe\"}")}
|
||||
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
||||
condition.evaluate(result, false)
|
||||
}
|
||||
b.ReportAllocs()
|
||||
|
@ -178,140 +178,140 @@ func TestCondition_evaluate(t *testing.T) {
|
||||
{
|
||||
Name: "body",
|
||||
Condition: Condition("[BODY] == test"),
|
||||
Result: &Result{body: []byte("test")},
|
||||
Result: &Result{Body: []byte("test")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY] == test",
|
||||
},
|
||||
{
|
||||
Name: "body-numerical-equal",
|
||||
Condition: Condition("[BODY] == 123"),
|
||||
Result: &Result{body: []byte("123")},
|
||||
Result: &Result{Body: []byte("123")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY] == 123",
|
||||
},
|
||||
{
|
||||
Name: "body-numerical-less-than",
|
||||
Condition: Condition("[BODY] < 124"),
|
||||
Result: &Result{body: []byte("123")},
|
||||
Result: &Result{Body: []byte("123")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY] < 124",
|
||||
},
|
||||
{
|
||||
Name: "body-numerical-greater-than",
|
||||
Condition: Condition("[BODY] > 122"),
|
||||
Result: &Result{body: []byte("123")},
|
||||
Result: &Result{Body: []byte("123")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY] > 122",
|
||||
},
|
||||
{
|
||||
Name: "body-numerical-greater-than-failure",
|
||||
Condition: Condition("[BODY] > 123"),
|
||||
Result: &Result{body: []byte("100")},
|
||||
Result: &Result{Body: []byte("100")},
|
||||
ExpectedSuccess: false,
|
||||
ExpectedOutput: "[BODY] (100) > 123",
|
||||
},
|
||||
{
|
||||
Name: "body-jsonpath",
|
||||
Condition: Condition("[BODY].status == UP"),
|
||||
Result: &Result{body: []byte("{\"status\":\"UP\"}")},
|
||||
Result: &Result{Body: []byte("{\"status\":\"UP\"}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY].status == UP",
|
||||
},
|
||||
{
|
||||
Name: "body-jsonpath-complex",
|
||||
Condition: Condition("[BODY].data.name == john"),
|
||||
Result: &Result{body: []byte("{\"data\": {\"id\": 1, \"name\": \"john\"}}")},
|
||||
Result: &Result{Body: []byte("{\"data\": {\"id\": 1, \"name\": \"john\"}}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY].data.name == john",
|
||||
},
|
||||
{
|
||||
Name: "body-jsonpath-complex-invalid",
|
||||
Condition: Condition("[BODY].data.name == john"),
|
||||
Result: &Result{body: []byte("{\"data\": {\"id\": 1}}")},
|
||||
Result: &Result{Body: []byte("{\"data\": {\"id\": 1}}")},
|
||||
ExpectedSuccess: false,
|
||||
ExpectedOutput: "[BODY].data.name (INVALID) == john",
|
||||
},
|
||||
{
|
||||
Name: "body-jsonpath-complex-len-invalid",
|
||||
Condition: Condition("len([BODY].data.name) == john"),
|
||||
Result: &Result{body: []byte("{\"data\": {\"id\": 1}}")},
|
||||
Result: &Result{Body: []byte("{\"data\": {\"id\": 1}}")},
|
||||
ExpectedSuccess: false,
|
||||
ExpectedOutput: "len([BODY].data.name) (INVALID) == john",
|
||||
},
|
||||
{
|
||||
Name: "body-jsonpath-double-placeholder",
|
||||
Condition: Condition("[BODY].user.firstName != [BODY].user.lastName"),
|
||||
Result: &Result{body: []byte("{\"user\": {\"firstName\": \"john\", \"lastName\": \"doe\"}}")},
|
||||
Result: &Result{Body: []byte("{\"user\": {\"firstName\": \"john\", \"lastName\": \"doe\"}}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY].user.firstName != [BODY].user.lastName",
|
||||
},
|
||||
{
|
||||
Name: "body-jsonpath-double-placeholder-failure",
|
||||
Condition: Condition("[BODY].user.firstName == [BODY].user.lastName"),
|
||||
Result: &Result{body: []byte("{\"user\": {\"firstName\": \"john\", \"lastName\": \"doe\"}}")},
|
||||
Result: &Result{Body: []byte("{\"user\": {\"firstName\": \"john\", \"lastName\": \"doe\"}}")},
|
||||
ExpectedSuccess: false,
|
||||
ExpectedOutput: "[BODY].user.firstName (john) == [BODY].user.lastName (doe)",
|
||||
},
|
||||
{
|
||||
Name: "body-jsonpath-when-body-is-array",
|
||||
Condition: Condition("[BODY][0].id == 1"),
|
||||
Result: &Result{body: []byte("[{\"id\": 1}, {\"id\": 2}]")},
|
||||
Result: &Result{Body: []byte("[{\"id\": 1}, {\"id\": 2}]")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY][0].id == 1",
|
||||
},
|
||||
{
|
||||
Name: "body-jsonpath-when-body-is-array-but-actual-body-is-not",
|
||||
Condition: Condition("[BODY][0].name == test"),
|
||||
Result: &Result{body: []byte("{\"statusCode\": 500, \"message\": \"Internal Server Error\"}")},
|
||||
Result: &Result{Body: []byte("{\"statusCode\": 500, \"message\": \"Internal Server Error\"}")},
|
||||
ExpectedSuccess: false,
|
||||
ExpectedOutput: "[BODY][0].name (INVALID) == test",
|
||||
},
|
||||
{
|
||||
Name: "body-jsonpath-complex-int",
|
||||
Condition: Condition("[BODY].data.id == 1"),
|
||||
Result: &Result{body: []byte("{\"data\": {\"id\": 1}}")},
|
||||
Result: &Result{Body: []byte("{\"data\": {\"id\": 1}}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY].data.id == 1",
|
||||
},
|
||||
{
|
||||
Name: "body-jsonpath-complex-array-int",
|
||||
Condition: Condition("[BODY].data[1].id == 2"),
|
||||
Result: &Result{body: []byte("{\"data\": [{\"id\": 1}, {\"id\": 2}, {\"id\": 3}]}")},
|
||||
Result: &Result{Body: []byte("{\"data\": [{\"id\": 1}, {\"id\": 2}, {\"id\": 3}]}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY].data[1].id == 2",
|
||||
},
|
||||
{
|
||||
Name: "body-jsonpath-complex-int-using-greater-than",
|
||||
Condition: Condition("[BODY].data.id > 0"),
|
||||
Result: &Result{body: []byte("{\"data\": {\"id\": 1}}")},
|
||||
Result: &Result{Body: []byte("{\"data\": {\"id\": 1}}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY].data.id > 0",
|
||||
},
|
||||
{
|
||||
Name: "body-jsonpath-complex-int-using-greater-than-failure",
|
||||
Condition: Condition("[BODY].data.id > 5"),
|
||||
Result: &Result{body: []byte("{\"data\": {\"id\": 1}}")},
|
||||
Result: &Result{Body: []byte("{\"data\": {\"id\": 1}}")},
|
||||
ExpectedSuccess: false,
|
||||
ExpectedOutput: "[BODY].data.id (1) > 5",
|
||||
},
|
||||
{
|
||||
Name: "body-jsonpath-float-using-greater-than-issue433", // As of v5.3.1, Gatus will convert a float to an int. We're losing precision, but it's better than just returning 0
|
||||
Condition: Condition("[BODY].balance > 100"),
|
||||
Result: &Result{body: []byte(`{"balance": "123.40000000000005"}`)},
|
||||
Result: &Result{Body: []byte(`{"balance": "123.40000000000005"}`)},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY].balance > 100",
|
||||
},
|
||||
{
|
||||
Name: "body-jsonpath-complex-int-using-less-than",
|
||||
Condition: Condition("[BODY].data.id < 5"),
|
||||
Result: &Result{body: []byte("{\"data\": {\"id\": 2}}")},
|
||||
Result: &Result{Body: []byte("{\"data\": {\"id\": 2}}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY].data.id < 5",
|
||||
},
|
||||
{
|
||||
Name: "body-jsonpath-complex-int-using-less-than-failure",
|
||||
Condition: Condition("[BODY].data.id < 5"),
|
||||
Result: &Result{body: []byte("{\"data\": {\"id\": 10}}")},
|
||||
Result: &Result{Body: []byte("{\"data\": {\"id\": 10}}")},
|
||||
ExpectedSuccess: false,
|
||||
ExpectedOutput: "[BODY].data.id (10) < 5",
|
||||
},
|
||||
@ -378,84 +378,84 @@ func TestCondition_evaluate(t *testing.T) {
|
||||
{
|
||||
Name: "len-body-jsonpath-complex",
|
||||
Condition: Condition("len([BODY].data.name) == 4"),
|
||||
Result: &Result{body: []byte("{\"data\": {\"name\": \"john\"}}")},
|
||||
Result: &Result{Body: []byte("{\"data\": {\"name\": \"john\"}}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "len([BODY].data.name) == 4",
|
||||
},
|
||||
{
|
||||
Name: "len-body-array",
|
||||
Condition: Condition("len([BODY]) == 3"),
|
||||
Result: &Result{body: []byte("[{\"id\": 1}, {\"id\": 2}, {\"id\": 3}]")},
|
||||
Result: &Result{Body: []byte("[{\"id\": 1}, {\"id\": 2}, {\"id\": 3}]")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "len([BODY]) == 3",
|
||||
},
|
||||
{
|
||||
Name: "len-body-keyed-array",
|
||||
Condition: Condition("len([BODY].data) == 3"),
|
||||
Result: &Result{body: []byte("{\"data\": [{\"id\": 1}, {\"id\": 2}, {\"id\": 3}]}")},
|
||||
Result: &Result{Body: []byte("{\"data\": [{\"id\": 1}, {\"id\": 2}, {\"id\": 3}]}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "len([BODY].data) == 3",
|
||||
},
|
||||
{
|
||||
Name: "len-body-array-invalid",
|
||||
Condition: Condition("len([BODY].data) == 8"),
|
||||
Result: &Result{body: []byte("{\"name\": \"john.doe\"}")},
|
||||
Result: &Result{Body: []byte("{\"name\": \"john.doe\"}")},
|
||||
ExpectedSuccess: false,
|
||||
ExpectedOutput: "len([BODY].data) (INVALID) == 8",
|
||||
},
|
||||
{
|
||||
Name: "len-body-string",
|
||||
Condition: Condition("len([BODY]) == 8"),
|
||||
Result: &Result{body: []byte("john.doe")},
|
||||
Result: &Result{Body: []byte("john.doe")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "len([BODY]) == 8",
|
||||
},
|
||||
{
|
||||
Name: "len-body-keyed-string",
|
||||
Condition: Condition("len([BODY].name) == 8"),
|
||||
Result: &Result{body: []byte("{\"name\": \"john.doe\"}")},
|
||||
Result: &Result{Body: []byte("{\"name\": \"john.doe\"}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "len([BODY].name) == 8",
|
||||
},
|
||||
{
|
||||
Name: "len-body-keyed-int",
|
||||
Condition: Condition("len([BODY].age) == 2"),
|
||||
Result: &Result{body: []byte(`{"age":18}`)},
|
||||
Result: &Result{Body: []byte(`{"age":18}`)},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "len([BODY].age) == 2",
|
||||
},
|
||||
{
|
||||
Name: "len-body-keyed-bool",
|
||||
Condition: Condition("len([BODY].adult) == 4"),
|
||||
Result: &Result{body: []byte(`{"adult":true}`)},
|
||||
Result: &Result{Body: []byte(`{"adult":true}`)},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "len([BODY].adult) == 4",
|
||||
},
|
||||
{
|
||||
Name: "len-body-object-inside-array",
|
||||
Condition: Condition("len([BODY][0]) == 23"),
|
||||
Result: &Result{body: []byte(`[{"age":18,"adult":true}]`)},
|
||||
Result: &Result{Body: []byte(`[{"age":18,"adult":true}]`)},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "len([BODY][0]) == 23",
|
||||
},
|
||||
{
|
||||
Name: "len-body-object-keyed-int-inside-array",
|
||||
Condition: Condition("len([BODY][0].age) == 2"),
|
||||
Result: &Result{body: []byte(`[{"age":18,"adult":true}]`)},
|
||||
Result: &Result{Body: []byte(`[{"age":18,"adult":true}]`)},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "len([BODY][0].age) == 2",
|
||||
},
|
||||
{
|
||||
Name: "len-body-keyed-bool-inside-array",
|
||||
Condition: Condition("len([BODY][0].adult) == 4"),
|
||||
Result: &Result{body: []byte(`[{"age":18,"adult":true}]`)},
|
||||
Result: &Result{Body: []byte(`[{"age":18,"adult":true}]`)},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "len([BODY][0].adult) == 4",
|
||||
},
|
||||
{
|
||||
Name: "len-body-object",
|
||||
Condition: Condition("len([BODY]) == 20"),
|
||||
Result: &Result{body: []byte("{\"name\": \"john.doe\"}")},
|
||||
Result: &Result{Body: []byte("{\"name\": \"john.doe\"}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "len([BODY]) == 20",
|
||||
},
|
||||
@ -463,49 +463,49 @@ func TestCondition_evaluate(t *testing.T) {
|
||||
{
|
||||
Name: "pat-body-1",
|
||||
Condition: Condition("[BODY] == pat(*john*)"),
|
||||
Result: &Result{body: []byte("{\"name\": \"john.doe\"}")},
|
||||
Result: &Result{Body: []byte("{\"name\": \"john.doe\"}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY] == pat(*john*)",
|
||||
},
|
||||
{
|
||||
Name: "pat-body-2",
|
||||
Condition: Condition("[BODY].name == pat(john*)"),
|
||||
Result: &Result{body: []byte("{\"name\": \"john.doe\"}")},
|
||||
Result: &Result{Body: []byte("{\"name\": \"john.doe\"}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY].name == pat(john*)",
|
||||
},
|
||||
{
|
||||
Name: "pat-body-failure",
|
||||
Condition: Condition("[BODY].name == pat(bob*)"),
|
||||
Result: &Result{body: []byte("{\"name\": \"john.doe\"}")},
|
||||
Result: &Result{Body: []byte("{\"name\": \"john.doe\"}")},
|
||||
ExpectedSuccess: false,
|
||||
ExpectedOutput: "[BODY].name (john.doe) == pat(bob*)",
|
||||
},
|
||||
{
|
||||
Name: "pat-body-html",
|
||||
Condition: Condition("[BODY] == pat(*<div id=\"user\">john.doe</div>*)"),
|
||||
Result: &Result{body: []byte(`<!DOCTYPE html><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body><div id="user">john.doe</div></body></html>`)},
|
||||
Result: &Result{Body: []byte(`<!DOCTYPE html><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body><div id="user">john.doe</div></body></html>`)},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY] == pat(*<div id=\"user\">john.doe</div>*)",
|
||||
},
|
||||
{
|
||||
Name: "pat-body-html-failure",
|
||||
Condition: Condition("[BODY] == pat(*<div id=\"user\">john.doe</div>*)"),
|
||||
Result: &Result{body: []byte(`<!DOCTYPE html><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body><div id="user">jane.doe</div></body></html>`)},
|
||||
Result: &Result{Body: []byte(`<!DOCTYPE html><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body><div id="user">jane.doe</div></body></html>`)},
|
||||
ExpectedSuccess: false,
|
||||
ExpectedOutput: "[BODY] (<!DOCTYPE html><html lang...(truncated)) == pat(*<div id=\"user\">john.doe</div>*)",
|
||||
},
|
||||
{
|
||||
Name: "pat-body-html-failure-alt",
|
||||
Condition: Condition("pat(*<div id=\"user\">john.doe</div>*) == [BODY]"),
|
||||
Result: &Result{body: []byte(`<!DOCTYPE html><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body><div id="user">jane.doe</div></body></html>`)},
|
||||
Result: &Result{Body: []byte(`<!DOCTYPE html><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body><div id="user">jane.doe</div></body></html>`)},
|
||||
ExpectedSuccess: false,
|
||||
ExpectedOutput: "pat(*<div id=\"user\">john.doe</div>*) == [BODY] (<!DOCTYPE html><html lang...(truncated))",
|
||||
},
|
||||
{
|
||||
Name: "pat-body-in-array",
|
||||
Condition: Condition("[BODY].data == pat(*Whatever*)"),
|
||||
Result: &Result{body: []byte("{\"data\": [\"hello\", \"world\", \"Whatever\"]}")},
|
||||
Result: &Result{Body: []byte("{\"data\": [\"hello\", \"world\", \"Whatever\"]}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY].data == pat(*Whatever*)",
|
||||
},
|
||||
@ -541,21 +541,21 @@ func TestCondition_evaluate(t *testing.T) {
|
||||
{
|
||||
Name: "any-body-1",
|
||||
Condition: Condition("[BODY].name == any(john.doe, jane.doe)"),
|
||||
Result: &Result{body: []byte("{\"name\": \"john.doe\"}")},
|
||||
Result: &Result{Body: []byte("{\"name\": \"john.doe\"}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY].name == any(john.doe, jane.doe)",
|
||||
},
|
||||
{
|
||||
Name: "any-body-2",
|
||||
Condition: Condition("[BODY].name == any(john.doe, jane.doe)"),
|
||||
Result: &Result{body: []byte("{\"name\": \"jane.doe\"}")},
|
||||
Result: &Result{Body: []byte("{\"name\": \"jane.doe\"}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "[BODY].name == any(john.doe, jane.doe)",
|
||||
},
|
||||
{
|
||||
Name: "any-body-failure",
|
||||
Condition: Condition("[BODY].name == any(john.doe, jane.doe)"),
|
||||
Result: &Result{body: []byte("{\"name\": \"bob\"}")},
|
||||
Result: &Result{Body: []byte("{\"name\": \"bob\"}")},
|
||||
ExpectedSuccess: false,
|
||||
ExpectedOutput: "[BODY].name (bob) == any(john.doe, jane.doe)",
|
||||
},
|
||||
@ -599,14 +599,14 @@ func TestCondition_evaluate(t *testing.T) {
|
||||
{
|
||||
Name: "has",
|
||||
Condition: Condition("has([BODY].errors) == false"),
|
||||
Result: &Result{body: []byte("{}")},
|
||||
Result: &Result{Body: []byte("{}")},
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "has([BODY].errors) == false",
|
||||
},
|
||||
{
|
||||
Name: "has-key-of-map",
|
||||
Condition: Condition("has([BODY].article) == true"),
|
||||
Result: &Result{body: []byte("{\n \"article\": {\n \"id\": 123,\n \"title\": \"Hello, world!\",\n \"author\": \"John Doe\",\n \"tags\": [\"hello\", \"world\"],\n \"content\": \"I really like Gatus!\"\n }\n}")},
|
||||
Result: &Result{Body: []byte("{\n \"article\": {\n \"id\": 123,\n \"title\": \"Hello, world!\",\n \"author\": \"John Doe\",\n \"tags\": [\"hello\", \"world\"],\n \"content\": \"I really like Gatus!\"\n }\n}")},
|
||||
DontResolveFailedConditions: false,
|
||||
ExpectedSuccess: true,
|
||||
ExpectedOutput: "has([BODY].article) == true",
|
||||
@ -614,14 +614,14 @@ func TestCondition_evaluate(t *testing.T) {
|
||||
{
|
||||
Name: "has-failure",
|
||||
Condition: Condition("has([BODY].errors) == false"),
|
||||
Result: &Result{body: []byte("{\"errors\": [\"1\"]}")},
|
||||
Result: &Result{Body: []byte("{\"errors\": [\"1\"]}")},
|
||||
ExpectedSuccess: false,
|
||||
ExpectedOutput: "has([BODY].errors) (true) == false",
|
||||
},
|
||||
{
|
||||
Name: "has-failure-but-dont-resolve",
|
||||
Condition: Condition("has([BODY].errors) == false"),
|
||||
Result: &Result{body: []byte("{\"errors\": [\"1\"]}")},
|
||||
Result: &Result{Body: []byte("{\"errors\": [\"1\"]}")},
|
||||
DontResolveFailedConditions: true,
|
||||
ExpectedSuccess: false,
|
||||
ExpectedOutput: "has([BODY].errors) == false",
|
||||
|
12
core/dns.go
12
core/dns.go
@ -61,26 +61,26 @@ func (d *DNS) query(url string, result *Result) {
|
||||
switch rr.Header().Rrtype {
|
||||
case dns.TypeA:
|
||||
if a, ok := rr.(*dns.A); ok {
|
||||
result.body = []byte(a.A.String())
|
||||
result.Body = []byte(a.A.String())
|
||||
}
|
||||
case dns.TypeAAAA:
|
||||
if aaaa, ok := rr.(*dns.AAAA); ok {
|
||||
result.body = []byte(aaaa.AAAA.String())
|
||||
result.Body = []byte(aaaa.AAAA.String())
|
||||
}
|
||||
case dns.TypeCNAME:
|
||||
if cname, ok := rr.(*dns.CNAME); ok {
|
||||
result.body = []byte(cname.Target)
|
||||
result.Body = []byte(cname.Target)
|
||||
}
|
||||
case dns.TypeMX:
|
||||
if mx, ok := rr.(*dns.MX); ok {
|
||||
result.body = []byte(mx.Mx)
|
||||
result.Body = []byte(mx.Mx)
|
||||
}
|
||||
case dns.TypeNS:
|
||||
if ns, ok := rr.(*dns.NS); ok {
|
||||
result.body = []byte(ns.Ns)
|
||||
result.Body = []byte(ns.Ns)
|
||||
}
|
||||
default:
|
||||
result.body = []byte("query type is not supported yet")
|
||||
result.Body = []byte("query type is not supported yet")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -90,12 +90,12 @@ func TestIntegrationQuery(t *testing.T) {
|
||||
}
|
||||
if test.inputDNS.QueryType == "NS" {
|
||||
// Because there are often multiple nameservers backing a single domain, we'll only look at the suffix
|
||||
if !pattern.Match(test.expectedBody, string(result.body)) {
|
||||
t.Errorf("got %s, expected result %s,", string(result.body), test.expectedBody)
|
||||
if !pattern.Match(test.expectedBody, string(result.Body)) {
|
||||
t.Errorf("got %s, expected result %s,", string(result.Body), test.expectedBody)
|
||||
}
|
||||
} else {
|
||||
if string(result.body) != test.expectedBody {
|
||||
t.Errorf("got %s, expected result %s,", string(result.body), test.expectedBody)
|
||||
if string(result.Body) != test.expectedBody {
|
||||
t.Errorf("got %s, expected result %s,", string(result.Body), test.expectedBody)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -280,8 +280,6 @@ func (endpoint *Endpoint) EvaluateHealth() *Result {
|
||||
}
|
||||
}
|
||||
result.Timestamp = time.Now()
|
||||
// No need to keep the body after the endpoint has been evaluated
|
||||
result.body = nil
|
||||
// Clean up parameters that we don't need to keep in the results
|
||||
if endpoint.UIConfig.HideURL {
|
||||
for errIdx, errorString := range result.Errors {
|
||||
@ -356,9 +354,9 @@ func (endpoint *Endpoint) call(result *Result) {
|
||||
}
|
||||
result.HTTPStatus = response.StatusCode
|
||||
result.Connected = response.StatusCode > 0
|
||||
// Only read the body if there's a condition that uses the BodyPlaceholder
|
||||
// Only read the Body if there's a condition that uses the BodyPlaceholder
|
||||
if endpoint.needsToReadBody() {
|
||||
result.body, err = io.ReadAll(response.Body)
|
||||
result.Body, err = io.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
result.AddError("error reading response body:" + err.Error())
|
||||
}
|
||||
@ -387,7 +385,7 @@ func (endpoint *Endpoint) buildHTTPRequest() *http.Request {
|
||||
return request
|
||||
}
|
||||
|
||||
// needsToReadBody checks if there's any condition that requires the response body to be read
|
||||
// needsToReadBody checks if there's any condition that requires the response Body to be read
|
||||
func (endpoint *Endpoint) needsToReadBody() bool {
|
||||
for _, condition := range endpoint.Conditions {
|
||||
if condition.hasBodyPlaceholder() {
|
||||
|
@ -44,12 +44,11 @@ type Result struct {
|
||||
// DomainExpiration is the duration before the domain expires
|
||||
DomainExpiration time.Duration `json:"-"`
|
||||
|
||||
// body is the response body
|
||||
// Body is the response body
|
||||
//
|
||||
// Note that this variable is only used during the evaluation of an Endpoint's health.
|
||||
// This means that the call Endpoint.EvaluateHealth both populates the body (if necessary)
|
||||
// and sets it to nil after the evaluation has been completed.
|
||||
body []byte
|
||||
// Note that this field is not persisted in the storage.
|
||||
// It is used for health evaluation as well as debugging purposes.
|
||||
Body []byte `json:"-"`
|
||||
}
|
||||
|
||||
// AddError adds an error to the result's list of errors.
|
||||
|
@ -65,14 +65,11 @@ func execute(endpoint *core.Endpoint, alertingConfig *alerting.Config, maintenan
|
||||
metrics.PublishMetricsForEndpoint(endpoint, result)
|
||||
}
|
||||
UpdateEndpointStatuses(endpoint, result)
|
||||
log.Printf(
|
||||
"[watchdog][execute] Monitored group=%s; endpoint=%s; success=%v; errors=%d; duration=%s",
|
||||
endpoint.Group,
|
||||
endpoint.Name,
|
||||
result.Success,
|
||||
len(result.Errors),
|
||||
result.Duration.Round(time.Millisecond),
|
||||
)
|
||||
if debug && !result.Success {
|
||||
log.Printf("[watchdog][execute] Monitored group=%s; endpoint=%s; success=%v; errors=%d; duration=%s; body=%s", endpoint.Group, endpoint.Name, result.Success, len(result.Errors), result.Duration.Round(time.Millisecond), result.Body)
|
||||
} else {
|
||||
log.Printf("[watchdog][execute] Monitored group=%s; endpoint=%s; success=%v; errors=%d; duration=%s", endpoint.Group, endpoint.Name, result.Success, len(result.Errors), result.Duration.Round(time.Millisecond))
|
||||
}
|
||||
if !maintenanceConfig.IsUnderMaintenance() {
|
||||
// TODO: Consider moving this after the monitoring lock is unlocked? I mean, how much noise can a single alerting provider cause...
|
||||
HandleAlerting(endpoint, result, alertingConfig, debug)
|
||||
|
Loading…
Reference in New Issue
Block a user