samedi 31 octobre 2015

Data returned as json with websocketpp but as Blob with messagepack

This is weird. I have modified a websocket-server example using websocketpp written in C++. It parses incoming stringified json-data from a client using nlohmann/json. Data is returned to the client in json-format, parsed and updating a hmtl div. All fine so far.

Then I wanted to compress json data from the client using messagepack, parse and return it in the same json-format but now I get an error since the data is now a [object Blob]. I put wireshark on but they capture exactly the same information in both scenarios.

Both are returned as

${"cnt":4,"data":"test","type":"msg"}

and have length 38.

In chrome I get the error

Uncaught SyntaxError: Unexpected token o

Here is the client before messagepack is added:

function sendMessage () {
    var m = document.getElementById("messageField").value;
    var msg = {
        "type": "msg",
        "data": m
    }
    msg = JSON.stringify(msg);
    ws.send(msg);
}

And the C++ server before message pack is added:

void on_message(connection_hdl hdl, server::message_ptr msg) {
    connection_ptr con = m_server.get_con_from_hdl(hdl);

    std::string payload = msg->get_payload();
    try {
        auto jdata = nlohmann::json::parse(payload);

        if (jdata["type"] == "lgn") {
            std::string lname = jdata["data"];
            if (con->name == "") {
                con->name = lname;
            }
        }

        if (jdata["type"] == "msg") {
            std::string clientmsg = jdata["data"];
            jdata["cnt"] = clientmsg.length();
            msg->set_payload(jdata.dump());
            m_server.send(hdl, msg);
        }
    } catch (const std::exception& e) {
        msg->set_payload("Unable to parse json");
        m_server.send(hdl, msg);
        std::cerr << "Unable to parse json: " << e.what() << std::endl;
    }
}

Pretty basic. Here are the client and server after messagepack was added:

function sendMessage () {
    var m = document.getElementById("messageField").value;
    var msg = {
        "type": "msg",
        "data": m
    }
    msg = JSON.stringify(msg);
    var buffer = msgpack.encode(msg);
    ws.send(buffer);
}

Only adding

var buffer = msgpack.encode(msg);

and changing ws.send() accordingly.

void on_message(connection_hdl hdl, server::message_ptr msg) {
    connection_ptr con = m_server.get_con_from_hdl(hdl);

    std::string payload = msg->get_payload();

    // Parse messagepack
    msgpack::unpacked unpacked_msg;
    msgpack::unpack(&unpacked_msg, payload.data(), payload.size());
    msgpack::object obj = unpacked_msg.get();
    std::string sobj;
    obj.convert(&sobj);

    try {
        auto jdata = nlohmann::json::parse(sobj);

        if (jdata["type"] == "lgn") {
            std::string lname = jdata["data"];
            if (con->name == "") {
                con->name = lname;
            }
        }

        if (jdata["type"] == "msg") {
            std::string clientmsg = jdata["data"];
            jdata["cnt"] = clientmsg.length();
            msg->set_payload(jdata.dump());
            m_server.send(hdl, msg);
        }
    } catch (const std::exception& e) {
        msg->set_payload("Unable to parse json");
        m_server.send(hdl, msg);
        std::cerr << "Unable to parse json: " << e.what() << std::endl;
    }
}

Adding

    // Parse messagepack
    msgpack::unpacked unpacked_msg;
    msgpack::unpack(&unpacked_msg, payload.data(), payload.size());
    msgpack::object obj = unpacked_msg.get();
    std::string sobj;
    obj.convert(&sobj);

and changing nlohmann::json::parse() accordingly.

The strange thing is that I only use messagepack atm. to compress incoming json data but not out. I will use it both ways if this is resolved. There must be something I'm overlooking and help is appreciated.

Aucun commentaire:

Enregistrer un commentaire