github.com/goplus/yap@v0.8.1/ytest/response.go (about) 1 /* 2 * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package ytest 18 19 import ( 20 "encoding/json" 21 "io" 22 "net/http" 23 "net/url" 24 25 "github.com/goplus/yap/test" 26 ) 27 28 type Response struct { 29 code int 30 header http.Header 31 raw []byte 32 mime string 33 body any 34 } 35 36 func newResponse(resp *http.Response) *Response { 37 raw, err := io.ReadAll(resp.Body) 38 if err != nil { 39 test.Fatal("ReadAll resp.Body:", err) 40 } 41 return &Response{ 42 code: resp.StatusCode, 43 header: resp.Header, 44 raw: raw, 45 } 46 } 47 48 // Code returns the status code of this response. 49 func (p *Response) Code() int { 50 return p.code 51 } 52 53 func (p *Response) matchCode(t CaseT, code any) { 54 t.Helper() 55 switch v := code.(type) { 56 case int: 57 test.Gopt_Case_MatchTBase(t, p.code, v) 58 case *test.Var__0[int]: 59 v.Match(t, p.code) 60 default: 61 t.Fatalf("match status code failed - unexpected type: %T\n", code) 62 } 63 } 64 65 // Header returns header of this response. 66 func (p *Response) Header() http.Header { 67 return p.header 68 } 69 70 func (p *Response) matchHeader(t CaseT, key string, value any) { 71 t.Helper() 72 switch v := value.(type) { 73 case string: 74 test.Gopt_Case_MatchTBase(t, v, p.header.Get(key)) 75 case []string: 76 test.Gopt_Case_MatchBaseSlice(t, v, p.header[key]) 77 case test.TySet[string]: 78 test.Gopt_Case_MatchSet(t, v, p.header[key]) 79 case *test.Var__0[string]: 80 v.Match(t, p.header.Get(key)) 81 case *test.Var__3[[]string]: 82 v.Match(t, p.header[key]) 83 default: 84 t.Fatalf("match header failed! unexpected value type: %T\n", value) 85 } 86 } 87 88 // RawBody returns raw response body as []byte (byte slice). 89 func (p *Response) RawBody() []byte { 90 return p.raw 91 } 92 93 // Body returns response body decoded according Content-Type. 94 func (p *Response) Body() (ret any) { 95 if p.mime == mimeNone { 96 mime := p.header.Get("Content-Type") 97 switch mime { 98 case mimeJson: 99 if err := json.Unmarshal(p.raw, &ret); err != nil { 100 test.Fatal("json.Unmarshal resp.Body:", err) 101 } 102 case mimeForm: 103 form, err := url.ParseQuery(string(p.raw)) 104 if err != nil { 105 test.Fatal("url.ParseQuery resp.Body:", err) 106 } 107 ret = form 108 case mimeNone: 109 mime = mimeBinary 110 fallthrough 111 default: 112 ret = p.raw 113 } 114 p.mime, p.body = mime, ret 115 } 116 return p.body 117 } 118 119 func (p *Response) matchBody(t CaseT, bodyType string, body any) { 120 t.Helper() 121 mime := p.header.Get("Content-Type") 122 if mime != bodyType { 123 t.Fatalf("resp.MatchBody: unmatched mime type - got: %s, expected: %s\n", mime, bodyType) 124 } 125 test.Gopt_Case_MatchAny(t, body, p.Body()) 126 }