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  }