mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-21 18:37:45 +08:00
117 lines
2.8 KiB
Go
117 lines
2.8 KiB
Go
package harness
|
|
|
|
import (
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"text/template"
|
|
"time"
|
|
)
|
|
|
|
// HTTPClient is an HTTP client with some conveniences for testing.
|
|
// URLs are constructed from a base URL.
|
|
// The response body is buffered into a string.
|
|
// Internal errors cause panics so that tests don't need to check errors.
|
|
// The paths are evaluated as Go templates for readable string interpolation.
|
|
type HTTPClient struct {
|
|
Client *http.Client
|
|
BaseURL string
|
|
|
|
Timeout time.Duration
|
|
TemplateData any
|
|
}
|
|
|
|
type HTTPResponse struct {
|
|
Body string
|
|
StatusCode int
|
|
Headers http.Header
|
|
|
|
// The raw response. The body will be closed on this response.
|
|
Resp *http.Response
|
|
}
|
|
|
|
func (c *HTTPClient) WithHeader(k, v string) func(h *http.Request) {
|
|
return func(h *http.Request) {
|
|
h.Header.Add(k, v)
|
|
}
|
|
}
|
|
|
|
func (c *HTTPClient) DisableRedirects() *HTTPClient {
|
|
c.Client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
|
return http.ErrUseLastResponse
|
|
}
|
|
return c
|
|
}
|
|
|
|
// Do executes the request unchanged.
|
|
func (c *HTTPClient) Do(req *http.Request) *HTTPResponse {
|
|
log.Debugf("making HTTP req %s to %q with headers %+v", req.Method, req.URL.String(), req.Header)
|
|
resp, err := c.Client.Do(req)
|
|
if resp != nil && resp.Body != nil {
|
|
defer resp.Body.Close()
|
|
}
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
bodyStr, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return &HTTPResponse{
|
|
Body: string(bodyStr),
|
|
StatusCode: resp.StatusCode,
|
|
Headers: resp.Header,
|
|
Resp: resp,
|
|
}
|
|
}
|
|
|
|
// BuildURL constructs a request URL from the given path by interpolating the string and then appending it to the base URL.
|
|
func (c *HTTPClient) BuildURL(urlPath string) string {
|
|
sb := &strings.Builder{}
|
|
err := template.Must(template.New("test").Parse(urlPath)).Execute(sb, c.TemplateData)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
renderedPath := sb.String()
|
|
return c.BaseURL + renderedPath
|
|
}
|
|
|
|
func (c *HTTPClient) Get(urlPath string, opts ...func(*http.Request)) *HTTPResponse {
|
|
req, err := http.NewRequest(http.MethodGet, c.BuildURL(urlPath), nil)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
for _, o := range opts {
|
|
o(req)
|
|
}
|
|
return c.Do(req)
|
|
}
|
|
|
|
func (c *HTTPClient) Post(urlPath string, body io.Reader, opts ...func(*http.Request)) *HTTPResponse {
|
|
req, err := http.NewRequest(http.MethodPost, c.BuildURL(urlPath), body)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
for _, o := range opts {
|
|
o(req)
|
|
}
|
|
return c.Do(req)
|
|
}
|
|
|
|
func (c *HTTPClient) PostStr(urlpath, body string, opts ...func(*http.Request)) *HTTPResponse {
|
|
r := strings.NewReader(body)
|
|
return c.Post(urlpath, r, opts...)
|
|
}
|
|
|
|
func (c *HTTPClient) Head(urlPath string, opts ...func(*http.Request)) *HTTPResponse {
|
|
req, err := http.NewRequest(http.MethodHead, c.BuildURL(urlPath), nil)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
for _, o := range opts {
|
|
o(req)
|
|
}
|
|
return c.Do(req)
|
|
}
|