Node-fetch: response.arrayBuffer() handles TypedArrays wrong

Created on 6 Jul 2018  ·  5Comments  ·  Source: node-fetch/node-fetch

If I pass TypedArrays like Uint8Array as a response body, and call .arrayBuffer() on that response the bytes in the response get shifted somehow.

const response = new Response(
  Uint16Array.from([..."foo bar"], c => c.codePointAt(0)),
);

const arrayBuffer = await response.arrayBuffer();
String.fromCodePoint(...new Uint16Array(arrayBuffer));

With a browser, I simply get back "foo bar", but with node-fetch I get some nonsense back "〱ⰲㄱⰱㄱⰱ㈳㤬ⰸ㜹ㄬ㐱".

Looking at the returned ArrayBuffer I see that the byteLength is off. It should be 14 (two bytes per character), but it is 24. Further, if I change to a Uint8Array I just get back "102,111,111,32,98,97,114"—the code points as a string. It is as if TypedArrays double encodes the byte array.

See node-fetch behaviour here: https://runkit.com/runarberg/5b3e883209257b00121b1a6e
See browser behaviour here: https://codepen.io/runarberg/pen/RJzarm

All 5 comments

I just ran into this as well. Can be reproduced with:

const { Response } = require('node-fetch');
const ta = Uint8Array.from([1, 2, 3]);
const r = new Response(ta);
r.arrayBuffer().then(ab => {
  const dv = new DataView(ab);
  console.log({
    length: dv.byteLength,
    zero: dv.getUint8(0),
    one: dv.getUint8(1),
    two: dv.getUint8(2)
  });
});

Get the result:

{
  "length": 5,
  "zero": 49,
  "one": 44,
  "two": 50
}

Rather than the expected:

{
  "length": 3,
  "zero": 1,
  "one": 2,
  "two": 3
}

I think the bug is in the Response constructor rather then in Body.prototype.arrayBuffer. Funny enough, "1".codePointAt(0) is 49, ",".codePointAt(0) is 44, "2".codePointAt(0) is 50. You can guess what dv.getUint8(3) and dv.getUint8(4) will give you.

In fact if you run new Response(Uint8Array.from([1, 2, 3])).text() you get the string "1,2,3" whereas the correct response should be a string with the codepoints 1, 2, and 3 respectively "���".

This seems to have been implemented upstream in #457 and #460 but now the the body will be consumed as empty (new bug). I created a pull request that fixes that (#484)

I came to the same conclusion. Thanks for putting up a PR 😄!

I actually fixed this in https://github.com/bitinn/node-fetch/pull/464, but forgot to merge it :(

Sorry about that folks. I'll go ahead and patch it up ASAP.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mikeconley12 picture mikeconley12  ·  4Comments

normanrz picture normanrz  ·  3Comments

teolag picture teolag  ·  5Comments

jimliang picture jimliang  ·  4Comments

KamasamaK picture KamasamaK  ·  3Comments