github.com/onsi/gomega@v1.32.0/matchers/have_http_body_matcher.go (about) 1 package matchers 2 3 import ( 4 "fmt" 5 "net/http" 6 "net/http/httptest" 7 8 "github.com/onsi/gomega/format" 9 "github.com/onsi/gomega/internal/gutil" 10 "github.com/onsi/gomega/types" 11 ) 12 13 type HaveHTTPBodyMatcher struct { 14 Expected interface{} 15 cachedResponse interface{} 16 cachedBody []byte 17 } 18 19 func (matcher *HaveHTTPBodyMatcher) Match(actual interface{}) (bool, error) { 20 body, err := matcher.body(actual) 21 if err != nil { 22 return false, err 23 } 24 25 switch e := matcher.Expected.(type) { 26 case string: 27 return (&EqualMatcher{Expected: e}).Match(string(body)) 28 case []byte: 29 return (&EqualMatcher{Expected: e}).Match(body) 30 case types.GomegaMatcher: 31 return e.Match(body) 32 default: 33 return false, fmt.Errorf("HaveHTTPBody matcher expects string, []byte, or GomegaMatcher. Got:\n%s", format.Object(matcher.Expected, 1)) 34 } 35 } 36 37 func (matcher *HaveHTTPBodyMatcher) FailureMessage(actual interface{}) (message string) { 38 body, err := matcher.body(actual) 39 if err != nil { 40 return fmt.Sprintf("failed to read body: %s", err) 41 } 42 43 switch e := matcher.Expected.(type) { 44 case string: 45 return (&EqualMatcher{Expected: e}).FailureMessage(string(body)) 46 case []byte: 47 return (&EqualMatcher{Expected: e}).FailureMessage(body) 48 case types.GomegaMatcher: 49 return e.FailureMessage(body) 50 default: 51 return fmt.Sprintf("HaveHTTPBody matcher expects string, []byte, or GomegaMatcher. Got:\n%s", format.Object(matcher.Expected, 1)) 52 } 53 } 54 55 func (matcher *HaveHTTPBodyMatcher) NegatedFailureMessage(actual interface{}) (message string) { 56 body, err := matcher.body(actual) 57 if err != nil { 58 return fmt.Sprintf("failed to read body: %s", err) 59 } 60 61 switch e := matcher.Expected.(type) { 62 case string: 63 return (&EqualMatcher{Expected: e}).NegatedFailureMessage(string(body)) 64 case []byte: 65 return (&EqualMatcher{Expected: e}).NegatedFailureMessage(body) 66 case types.GomegaMatcher: 67 return e.NegatedFailureMessage(body) 68 default: 69 return fmt.Sprintf("HaveHTTPBody matcher expects string, []byte, or GomegaMatcher. Got:\n%s", format.Object(matcher.Expected, 1)) 70 } 71 } 72 73 // body returns the body. It is cached because once we read it in Match() 74 // the Reader is closed and it is not readable again in FailureMessage() 75 // or NegatedFailureMessage() 76 func (matcher *HaveHTTPBodyMatcher) body(actual interface{}) ([]byte, error) { 77 if matcher.cachedResponse == actual && matcher.cachedBody != nil { 78 return matcher.cachedBody, nil 79 } 80 81 body := func(a *http.Response) ([]byte, error) { 82 if a.Body != nil { 83 defer a.Body.Close() 84 var err error 85 matcher.cachedBody, err = gutil.ReadAll(a.Body) 86 if err != nil { 87 return nil, fmt.Errorf("error reading response body: %w", err) 88 } 89 } 90 return matcher.cachedBody, nil 91 } 92 93 switch a := actual.(type) { 94 case *http.Response: 95 matcher.cachedResponse = a 96 return body(a) 97 case *httptest.ResponseRecorder: 98 matcher.cachedResponse = a 99 return body(a.Result()) 100 default: 101 return nil, fmt.Errorf("HaveHTTPBody matcher expects *http.Response or *httptest.ResponseRecorder. Got:\n%s", format.Object(actual, 1)) 102 } 103 104 }