Read protobuf message from websocket connection

Hello guys,

Currently im working on loadtest for websocket, but it doesnt use usual message like JSON, but it was using protobuf message.
I was successfully to send protobuf message to server.
But when I want to read message from server and write on console using this code

     socket.on('message', function (message) {
        console.log(`Received message: ${message}`);
      });

that given me like this

Am I missed something here?

nb: i follow the steps in this repo GitHub - sparrowjack/k6_protobuff_demo: a demo implement the k6[https://k6.io] load test tool to send protobuf message to server

Hi there!

GitHub - sparrowjack/k6_protobuff_demo: a demo implement the k6[https://k6.io] load test tool

That’s an interesting project, thanks for sharing.

The problem is that you’re logging the stringified binary message, which will only output garbage.

I’m not familiar with the protobuf JS implementation, but have you tried deserializing the received message?

According to the API docs and that demo repo, I would try this:

socket.on('message', function (message) {
  let msg = new proto.Message();
  let dMsg = msg.deserializeBinary(message);
  // read fields from dMsg
});

Unfortunately, this is a bit hacky right now, since the WebSocket implementation in k6 only supports string messages. This should be easier now that ArrayBuffer is natively supported in goja (the JS VM k6 uses), and we’ll consider addressing this use case in upcoming versions.

seems like it doesnt work either bro @imiric :cry:

i think if i want to read the incoming message, i have to make kind of message mapping using the related .proto file
i read it from here GitHub - protobufjs/protobuf.js: Protocol Buffers for JavaScript (& TypeScript).

is k6 support to read typescript code?

What doesn’t work specifically? Do you get any errors?

That page mentions that TypeScript is optional and you can access fields in plain JS with bracket notation. That said, no, k6 doesn’t read TypeScript directly, but you could use a bundler like Webpack to pre-transform the TS to JS and load that in k6. See the template-es6 project for a start.

when i was using this method, it returned error like this

TypeError: Object has no member 'deserializeBinary'

even there are some code like this inside protofile_pb.js

/**
 * Deserializes binary data (in protobuf wire format).
 * @param {jspb.ByteSource} bytes The bytes to deserialize.
 * @return {!proto.proto.Pong}
 */
proto.proto.Pong.deserializeBinary = function(bytes) {
  var reader = new jspb.BinaryReader(bytes);
  var msg = new proto.proto.Pong;
  return proto.proto.Pong.deserializeBinaryFromReader(msg, reader);
};


/**
 * Deserializes binary data (in protobuf wire format) from the
 * given reader into the given message object.
 * @param {!proto.proto.Pong} msg The message object to deserialize into.
 * @param {!jspb.BinaryReader} reader The BinaryReader to use.
 * @return {!proto.proto.Pong}
 */
proto.proto.Pong.deserializeBinaryFromReader = function(msg, reader) {
  while (reader.nextField()) {
    if (reader.isEndGroup()) {
      break;
    }
    var field = reader.getFieldNumber();
    switch (field) {
    case 1:
      var value = /** @type {number} */ (reader.readInt32());
      msg.setEvent(value);
      break;
    case 2:
      var value = /** @type {number} */ (reader.readInt64());
      msg.setId(value);
      break;
    default:
      reader.skipField();
      break;
    }
  }
  return msg;
};

im still trying how to map the incoming message

nb: protofile_pb.js is a converted file from protofile.proto using protoc

hello guys, is there any updates for this issue?

Hi Gradito,

this issue is difficult to reproduce, so it slipped through the cracks, sorry about that.

Since the initial discussion, the binary support in k6 has improved and now the k6/ws module supports ArrayBuffer, so it should make working with binary data easier than before.

Can you share a Git repository with a minimal example that reproduces this? I’m not sure if it’s something with the way you’re bundling/loading protofile_pb.js or something with k6.

That code you shared seems to be only for the Pong WS response object. It might not be defined on whatever proto.Message() returns.

That said, there might be other ways of doing what you want. Take a look at this gist. Loading of the .proto file directly won’t work with k6, but the JSON example seems like it could. Note that you’ll need to convert the .proto to JSON beforehand, and then load it in k6 with open() instead of require().

Let us know if that works for you, otherwise please share a reproducible example.

1 Like

thankyou @imiric it works now!!
i combine ur suggestion to read protobuf and use npm packages then bundle it using GitHub - grafana/k6-template-es6: Template repository for bundling test projects into single test scripts runnable by k6
then i use GitHub - sparrowjack/k6_protobuff_demo: a demo implement the k6[https://k6.io] load test tool for send the message to server

thanks a lot!!