hildjj / node-cbor

Encode and decode CBOR documents, with both easy mode, streaming mode, and SAX-style evented mode.
MIT License
357 stars 73 forks source link

Cannot decode Uint8Array from websocket: Insufficient data #116

Closed freddi301 closed 3 years ago

freddi301 commented 3 years ago
import CBOR from "cbor";
import WebSocket from "ws";
import http from "http";

const port = 8086;
const server = http.createServer();
const wss = new WebSocket.Server({ server });

wss.on("connection", (ws) => {
  ws.on("message", (message) => {
    const { id, method, params } = CBOR.decode(message as Buffer);
    // @ts-ignore
    api[method](...params).then((result) => {
      console.log(CBOR.encode({ id, result }));
      ws.send(CBOR.encode({ id, result }));
    });
  });
});
server.listen(port);

export type API = typeof api;
const api = {
  async all() {
    return [{ hash: Buffer.from("hello"), block: Buffer.from("world") }];
  },
};
import React, { useEffect, useState } from "react";
import CBOR from "cbor";

function App() {
  const [state, setState] = useState<any>();
  useEffect(() => {
    api.all().then(setState);
  }, []);
  return <div></div>;
}

export default App;

var ws = new WebSocket("ws://localhost:8086");
ws.binaryType = "arraybuffer";
ws.addEventListener("message", (event) => {
  console.log(
    new Uint8Array(event.data),
    CBOR.encode({
      id: 1,
      result: [{ hash: Buffer.from("hello"), block: Buffer.from("world") }],
    })
  );
  const { id, result } = CBOR.decode(new Uint8Array(event.data));
  pendingRpcCalls.get(id)?.(result);
  pendingRpcCalls.delete(id);
});
let nextRpcId = 1;
const pendingRpcCalls = new Map<number, (result: any) => void>();
const api: import("../../backend/src").API = new Proxy({} as any, {
  get(target, method) {
    return (...params: any[]) =>
      new Promise((resolve) => {
        const id = nextRpcId++;
        pendingRpcCalls.set(id, resolve);
        const sendit = () => ws.send(CBOR.encode({ id, method, params }));
        if (ws.readyState === ws.OPEN) {
          sendit();
        } else {
          ws.addEventListener("open", sendit);
        }
      });
  },
});
freddi301 commented 3 years ago

solved with

const { id, result } = CBOR.decode(Buffer.from(event.data));
rivertam commented 3 years ago

Got this too -- difficult error message and it makes basically no sense (in my opinion).

image

Fun stuff!

hildjj commented 3 years ago

in the node10 branch, i've added support for decoding typed arrays and ArrayBuffers, which should make this problem go away, mostly.

hildjj commented 3 years ago

OK, this should work as of v6.0.0. Please re-open this ticket or file another one if you want it to work differently than it does.