Skip to content

Commit

Permalink
Return ArrayBuffer from binary response bodies
Browse files Browse the repository at this point in the history
This is a breaking change part of #1020.
  • Loading branch information
Ivan Mirić committed Mar 29, 2021
1 parent d62b5b2 commit 271a8d6
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 18 deletions.
1 change: 1 addition & 0 deletions js/modules/k6/http/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ func (h *HTTP) Request(ctx context.Context, method string, url goja.Value, args
if err != nil {
return nil, err
}
processResponse(ctx, resp, req.ResponseType)
return h.responseFromHttpext(resp), nil
}

Expand Down
46 changes: 28 additions & 18 deletions js/modules/k6/http/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1429,8 +1429,19 @@ func TestRequestArrayBufferBody(t *testing.T) {
var res = http.post("HTTPBIN_URL/post-arraybuffer", arr.buffer, { responseType: 'binary' });
if (res.status != 200) { throw new Error("wrong status: " + res.status) }
if (res.body != "%[2]s") { throw new Error(
"incorrect data: expected '%[2]s', received '" + res.body + "'") }
var resTyped = new Uint8Array(res.body);
var exp = new %[1]s([%[2]s]);
if (exp.length !== resTyped.length) {
throw new Error(
"incorrect data length: expected " + exp.length + ", received " + resTypedLength)
}
for (var i = 0; i < exp.length; i++) {
if (exp[i] !== resTyped[i]) {
throw new Error(
"incorrect data at index " + i + ": expected " + exp[i] + ", received " + resTyped[i])
}
}
`, tc.arr, tc.expected)))
assert.NoError(t, err)
})
Expand Down Expand Up @@ -1687,31 +1698,30 @@ func TestResponseTypes(t *testing.T) {
}
// Check binary transmission of the text response as well
var respTextInBin = http.get("HTTPBIN_URL/get-text", { responseType: "binary" }).body;
var respBin = http.get("HTTPBIN_URL/get-text", { responseType: "binary" });
// Hack to convert a utf-8 array to a JS string
var strConv = "";
function pad(n) { return n.length < 2 ? "0" + n : n; }
for( var i = 0; i < respTextInBin.length; i++ ) {
strConv += ( "%" + pad(respTextInBin[i].toString(16)));
}
strConv = decodeURIComponent(strConv);
// Convert a UTF-8 ArrayBuffer to a JS string
var respBinText = String.fromCharCode.apply(null, new Uint8Array(respBin.body));
var strConv = decodeURIComponent(escape(respBinText));
if (strConv !== expText) {
throw new Error("converted response body should be '" + expText + "' but was '" + strConv + "'");
}
http.post("HTTPBIN_URL/compare-text", respTextInBin);
http.post("HTTPBIN_URL/compare-text", respBin.body);
// Check binary response
var respBin = http.get("HTTPBIN_URL/get-bin", { responseType: "binary" }).body;
if (respBin.length !== expBinLength) {
throw new Error("response body length should be '" + expBinLength + "' but was '" + respBin.length + "'");
var respBin = http.get("HTTPBIN_URL/get-bin", { responseType: "binary" });
var respBinTyped = new Uint8Array(respBin.body);
if (expBinLength !== respBinTyped.length) {
throw new Error("response body length should be '" + expBinLength
+ "' but was '" + respBinTyped.length + "'");
}
for( var i = 0; i < respBin.length; i++ ) {
if ( respBin[i] !== i%256 ) {
throw new Error("expected value " + (i%256) + " to be at position " + i + " but it was " + respBin[i]);
for(var i = 0; i < respBinTyped.length; i++) {
if (respBinTyped[i] !== i%256) {
throw new Error("expected value " + (i%256) + " to be at position "
+ i + " but it was " + respBinTyped[i]);
}
}
http.post("HTTPBIN_URL/compare-bin", respBin);
http.post("HTTPBIN_URL/compare-bin", respBin.body);
`))
assert.NoError(t, err)

Expand Down
11 changes: 11 additions & 0 deletions js/modules/k6/http/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
package http

import (
"context"
"errors"
"fmt"
"net/url"
Expand All @@ -39,6 +40,16 @@ type Response struct {
h *HTTP
}

// processResponse stores the body as an ArrayBuffer if indicated by
// respType. This is done here instead of in httpext.readResponseBody to avoid
// a reverse dependency on js/common or goja.
func processResponse(ctx context.Context, resp *httpext.Response, respType httpext.ResponseType) {
if respType == httpext.ResponseTypeBinary {
rt := common.GetRuntime(ctx)
resp.Body = rt.NewArrayBuffer(resp.Body.([]byte))
}
}

func (h *HTTP) responseFromHttpext(resp *httpext.Response) *Response {
return &Response{Response: resp, h: h}
}
Expand Down
2 changes: 2 additions & 0 deletions lib/netext/httpext/compression.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ func readResponseBody(
case ResponseTypeBinary:
// Copy the data to a new slice before we return the buffer to the pool,
// because buf.Bytes() points to the underlying buffer byte slice.
// The ArrayBuffer wrapping will be done in the js/modules/k6/http
// package to avoid a reverse dependency, since it depends on goja.
binData := make([]byte, buf.Len())
copy(binData, buf.Bytes())
result = binData
Expand Down

0 comments on commit 271a8d6

Please sign in to comment.