mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
internal/testutil/request: add ReadJSONResponse utility
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
33
internal/testutil/request/helpers.go
Normal file
33
internal/testutil/request/helpers.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ReadBody read the specified ReadCloser content and returns it.
|
||||
func ReadBody(b io.ReadCloser) ([]byte, error) {
|
||||
defer func() { _ = b.Close() }()
|
||||
return io.ReadAll(b)
|
||||
}
|
||||
|
||||
// ReadJSONResponse reads a JSON response body into the given variable. it
|
||||
// returns an error for non-jSON responses, or when failing to unmarshal.
|
||||
func ReadJSONResponse[T any](resp *http.Response, v *T) error {
|
||||
if resp == nil {
|
||||
return errors.New("nil *http.Response")
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
mt, _, _ := mime.ParseMediaType(resp.Header.Get("Content-Type"))
|
||||
if mt != "application/json" {
|
||||
raw, _ := io.ReadAll(io.LimitReader(resp.Body, 8<<10))
|
||||
return fmt.Errorf("unexpected Content-Type: '%s' (body: %s)", mt, string(raw))
|
||||
}
|
||||
|
||||
return json.NewDecoder(resp.Body).Decode(v)
|
||||
}
|
||||
77
internal/testutil/request/helpers_test.go
Normal file
77
internal/testutil/request/helpers_test.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package request_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/moby/moby/v2/internal/testutil/request"
|
||||
"gotest.tools/v3/assert"
|
||||
)
|
||||
|
||||
func TestReadJSONResponse(t *testing.T) {
|
||||
type someResponse struct {
|
||||
Hello string `json:"Hello"`
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
body string
|
||||
contentType string
|
||||
expected someResponse
|
||||
expErr string
|
||||
}{
|
||||
{
|
||||
name: "valid JSON",
|
||||
body: `{"hello": "world"}`,
|
||||
contentType: "application/json",
|
||||
expected: someResponse{Hello: "world"},
|
||||
},
|
||||
{
|
||||
name: "valid JSON, utf-8",
|
||||
body: `{"hello": "world"}`,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
expected: someResponse{Hello: "world"},
|
||||
},
|
||||
{
|
||||
name: "malformed JSON",
|
||||
body: `{"hello": "world"`,
|
||||
contentType: "application/json",
|
||||
expErr: "unexpected EOF",
|
||||
},
|
||||
{
|
||||
name: "non-JSON",
|
||||
body: `<html><head><title>Page not found</title></head></html>`,
|
||||
contentType: "text/html",
|
||||
expErr: "unexpected Content-Type: 'text/html'",
|
||||
},
|
||||
{
|
||||
name: "nil response",
|
||||
expErr: "nil *http.Response",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var v someResponse
|
||||
|
||||
var resp *http.Response
|
||||
if tc.name != "nil response" {
|
||||
resp = &http.Response{
|
||||
Header: make(http.Header),
|
||||
Body: io.NopCloser(bytes.NewBufferString(tc.body)),
|
||||
}
|
||||
resp.Header.Set("Content-Type", tc.contentType)
|
||||
}
|
||||
|
||||
err := request.ReadJSONResponse(resp, &v)
|
||||
if tc.expErr != "" {
|
||||
assert.ErrorContains(t, err, tc.expErr)
|
||||
} else {
|
||||
assert.NilError(t, err)
|
||||
assert.DeepEqual(t, tc.expected, v)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -105,12 +105,6 @@ func Do(ctx context.Context, endpoint string, modifiers ...func(*Options)) (*htt
|
||||
return resp, body, err
|
||||
}
|
||||
|
||||
// ReadBody read the specified ReadCloser content and returns it
|
||||
func ReadBody(b io.ReadCloser) ([]byte, error) {
|
||||
defer b.Close()
|
||||
return io.ReadAll(b)
|
||||
}
|
||||
|
||||
// newRequest creates a new http Request to the specified host and endpoint, with the specified request modifiers
|
||||
func newRequest(endpoint string, opts *Options) (*http.Request, error) {
|
||||
hostURL, err := client.ParseHostURL(opts.host)
|
||||
|
||||
Reference in New Issue
Block a user