Sails.js socket.io protobuf.js encoded message causes error: "Illegal buffer" on decode in browser

Sails.js socket.io protobuf.js encoded message causes error: "Illegal buffer" on decode in browser

我正在向 this 示例添加 protobuf 消息加密。

为此我有:

Chat.proto

package Chat;

message Message{
    required string user = 1;
    optional string message = 2;
    optional string id = 3;

}

ChatController.js:

...
var builder = ProtoBuf.loadProtoFile(require('path').resolve(sails.config.appPath, "assets/proto/Chat.proto")),
                Message = builder.build("Chat").Message;

var encodeMessage = function (message) {
    "use strict";
    sails.log.info("WILL ENCODE", message);
    var msg = new Message(message);
    sails.log.info("ENCODED", msg);
    return msg;
};

module.exports = {

    addConv: function (req, res) {

        var data_from_client = req.params.all();

        if (req.isSocket && req.method === 'POST') {

            // This is the new message
            Chat.create(data_from_client).exec(function (err, data_from_client){
                Chat.publishCreate({ id: (data_from_client.id), 
            // I encode only on sending from server
                data : encodeMessage({
                    message: data_from_client.message,
                    user: data_from_client.user }).toBuffer()
                });
            });
        }
        else if (req.isSocket) {
            Chat.watch(req.socket);
            sails.log.info('USER SUBSCRIBED TO ' + req.socket.id);
        }
    }
};
前端

和 socketApp.js:

...
ProtoBuf.loadProtoFile("/proto/Chat.proto", function (err, builder) {
    Chat = builder.build("Chat"),
                    Message = Chat.Message;
});

socketApp.controller('ChatController', ['$http', '$log', '$scope', function ($http, $log, $scope) {

    var decodeMessage = function (message) {
        console.log("WILL DECODE", message);
        var msg = Message.decode(message); //Line 23 !Here goes the error!
        console.log("DECODED", msg);
        return msg;
    };

    ...

    io.socket.on('chat', function (obj, keys) {
        console.log('chat', obj, keys); //Says that object is: {id: 41, data: ArrayBuffer}
        if (obj.verb === 'created') {
            console.log(decodeMessage(obj.data));
            $scope.chatList.push(decodeMessage(obj.data));
            $scope.$digest();
        }

    });

    $scope.sendMsg = function () {
        ...
    };
}]);

每次客户端从服务器获取编码消息时我都会遇到错误:

Uncaught TypeError: Illegal bufferByteBuffer.wrap @ ByteBufferAB.js:390
ProtoBuf.Reflect.MessagePrototype.build.Message.decode @ ProtoBuf.js:2904
decodeMessage @ socketApp.js:23
(anonymous function) @ socketApp.js:56
u.8.Emitter.emit @ sails.io.js:3
u.5.Socket.onevent @ sails.io.js:3
u.5.Socket.onpacket @ sails.io.js:3
u.7.module.exports @ sails.io.js:3
u.8.Emitter.emit @ sails.io.js:3
u.3.Manager.ondecoded @ sails.io.js:3
u.7.module.exports @ sails.io.js:3
u.8.Emitter.emit @ sails.io.js:3
u.43.Decoder.add @ sails.io.js:5
u.3.Manager.ondata @ sails.io.js:3
u.7.module.exports @ sails.io.js:3
u.8.Emitter.emit @ sails.io.js:3
u.12.Socket.onPacket @ sails.io.js:3
(anonymous function) @ sails.io.js:3
u.8.Emitter.emit @ sails.io.js:3
u.13.Transport.onPacket @ sails.io.js:3
u.13.Transport.onData @ sails.io.js:3
u.18.WS.addEventListeners.ws.onmessage @ sails.io.js:4

怎么了?我怎样才能使这项工作?

sails-hook-sockets on receiving data by socket and providing it to other middlewares uses lodash's _.extend : See here: body : _.extend({}, options.incomingSailsIOMsg.params || {}, options.incomingSailsIOMsg.data || {}),,我希望在其他几个地方。以某种方式扩展刹车 ArrayBuffer。

所以我发现的唯一方法是在 sails-hook-sockets 处理之前反序列化消息。所以我可以在服务的某个地方写:

ProtoDeserializationService:

ProtoBuf.loadProtoFile("/proto/Chat.proto", function (err, builder) {
    Chat = builder.build("Chat"),  Message = Chat.Message;;

sails.io.on('connect', function (socket) {
        var _onevent = socket.onevent;

        sails.log.silly("socket_protobuf: Overriding socket.io onevent method to support deserialization of incoming message");

        /**
         * Overriden socket.io onevent metod that receives packages
         * 
         * If `packet.data.data` field contains fields `protobuf` and `model` then it should be deserialized according to Protocol Buffers message scheme with name stored in `model`.
         * 
         * @param {Object} packet           received data
         */
        socket.onevent = function (packet) {

            sails.log.silly("socket_protobuf: onevent");

            var args = packet.data || [],
                            data = args[1].data || args[1],
                            protobuf = data.protobuf || null,
                            model = data.model|| null;

            if (protobuf && model) {
                _.extend(data, Message.decode(protobuf));
                delete data.protobuf;
                delete data.model;
            }

            _onevent.call(this, packet);
        };
    });

但我写了更通用的解决方案:hook to be able to serialize protocol buffer messages on both plain socket.io requests and sails.socket.io Pub/Sub