github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/testing/http.go (about) 1 // Copyright 2018 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package testing 5 6 import ( 7 "io" 8 "net/http" 9 10 jujuhttp "github.com/juju/http/v2" 11 jc "github.com/juju/testing/checkers" 12 "github.com/juju/testing/httptesting" 13 gc "gopkg.in/check.v1" 14 15 "github.com/juju/juju/rpc/params" 16 jujuversion "github.com/juju/juju/version" 17 ) 18 19 // httpRequestParams holds parameters for the sendHTTPRequest methods. 20 type HTTPRequestParams struct { 21 // do is used to make the HTTP request. 22 // If it is nil, utils.GetNonValidatingHTTPClient().Do will be used. 23 // If the body reader implements io.Seeker, 24 // req.Body will also implement that interface. 25 Do func(req *http.Request) (*http.Response, error) 26 27 // expectError holds the error regexp to match 28 // against the error returned from the HTTP Do 29 // request. If it is empty, the error is expected to be 30 // nil. 31 ExpectError string 32 33 // ExpectStatus holds the expected HTTP status code. 34 // http.StatusOK is assumed if this is zero. 35 ExpectStatus int 36 37 // tag holds the tag to authenticate as. 38 Tag string 39 40 // password holds the password associated with the tag. 41 Password string 42 43 // method holds the HTTP method to use for the request. 44 Method string 45 46 // url holds the URL to send the HTTP request to. 47 URL string 48 49 // contentType holds the content type of the request. 50 ContentType string 51 52 // body holds the body of the request. 53 Body io.Reader 54 55 // extra headers are added to the http header 56 ExtraHeaders map[string]string 57 58 // jsonBody holds an object to be marshaled as JSON 59 // as the body of the request. If this is specified, body will 60 // be ignored and the Content-Type header will 61 // be set to application/json. 62 JSONBody interface{} 63 64 // nonce holds the machine nonce to provide in the header. 65 Nonce string 66 } 67 68 func SendHTTPRequest(c *gc.C, p HTTPRequestParams) *http.Response { 69 c.Logf("sendRequest: %s", p.URL) 70 hp := httptesting.DoRequestParams{ 71 Do: p.Do, 72 Method: p.Method, 73 URL: p.URL, 74 Body: p.Body, 75 JSONBody: p.JSONBody, 76 Header: make(http.Header), 77 Username: p.Tag, 78 Password: p.Password, 79 ExpectError: p.ExpectError, 80 ExpectStatus: p.ExpectStatus, 81 } 82 hp.Header.Set(params.JujuClientVersion, jujuversion.Current.String()) 83 if p.ContentType != "" { 84 hp.Header.Set("Content-Type", p.ContentType) 85 } 86 for key, value := range p.ExtraHeaders { 87 hp.Header.Set(key, value) 88 } 89 if p.Nonce != "" { 90 hp.Header.Set(params.MachineNonceHeader, p.Nonce) 91 } 92 if hp.Do == nil { 93 client := jujuhttp.NewClient(jujuhttp.WithSkipHostnameVerification(true)) 94 hp.Do = client.Do 95 } 96 return httptesting.Do(c, hp) 97 } 98 99 func AssertResponse(c *gc.C, resp *http.Response, expHTTPStatus int, expContentType string) []byte { 100 body, err := io.ReadAll(resp.Body) 101 _ = resp.Body.Close() 102 c.Assert(err, jc.ErrorIsNil) 103 c.Check(resp.StatusCode, gc.Equals, expHTTPStatus, gc.Commentf("body: %s", body)) 104 ctype := resp.Header.Get("Content-Type") 105 c.Assert(ctype, gc.Equals, expContentType) 106 return body 107 }