Thanks. follow the idea , here is my hack
js client side serializer
function toBytesInt32 (num) {
var arr = new Uint8Array([
(num & 0xff000000) >> 24,
(num & 0x00ff0000) >> 16,
(num & 0x0000ff00) >> 8,
(num & 0x000000ff)
]);
return arr;
}
function encode(msg, callback){
// check if system message
if(Object.keys(msg.payload).length == 0){
let payload = [ msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload]
return callback(JSON.stringify(payload))
}
else
{
var enc = new TextEncoder();
let pl = [ msg.join_ref, msg.ref, msg.topic, msg.event, {}]
let json_buf = enc.encode(JSON.stringify(pl));
let head = enc.encode("{=+}");
var data_length = toBytesInt32(msg.payload.length);
let d = new Uint8Array(head.length +data_length.length+msg.payload.length+json_obj_buf.length);
d.set(head);
d.set(data_length,head.length);
d.set(msg.payload,head.length+d_ua.length);
d.set(json_buf,head.length+data_length.length+msg.payload.length);
return callback(uint8ArrayP);
}
function arrayBufCompare(buf1,buf2)
{
if (buf1.length != buf2.length) return false;
for (var i = 0 ; i < 4 ; i++)
{
if (buf1[i] != buf2[i]) return false;
}
return true;
}
function decode(rawPayload, callback){
var dec = new TextDecoder("utf-8");
var enc = new TextEncoder();
var expect_head = enc.encode("{=+}");
var head_buf = new Uint8Array(rawPayload,0,4);
if(arrayBufCompare(head_buf,expect_head))
{
var data_size_buf = new Uint8Array(rawPayload,4,4);
let buffer = Buffer.from(data_size_buf);
var data_size = buffer.readUIntBE(0, buffer.length);
var data_buf = new Uint8Array(rawPayload,8,data_size);
var json_buf = new Uint8Array(rawPayload,8+data_size,rawPayload.byteLength - 8 - data_size);
var json_str = dec.decode(json_buf);
let [join_ref, ref, topic, event, payload] = JSON.parse(json_str);
payload["mydata"] = data_buf
return callback({join_ref, ref, topic, event, payload})
}
else
{
let [join_ref, ref, topic, event, payload] = JSON.parse(dec.decode(rawPayload))
return callback({join_ref, ref, topic, event, payload})
}
}
let socket = new Socket("/socket", {params: {token: window.userToken},
encode: encode, decode:decode, binaryType:'blob'})
custom serializer.ex
def decode!(iodata, _options) do
<<head::binary-size(4),data_size_b::binary-size(4),_::binary>> = iodata
if head == "{=+}" do
data_size = :binary.decode_unsigned(data_size_b)
<<_::binary-size(4),_::binary-size(4), my_data::binary-size(data_size),json_pkg::binary>> = iodata
[join_ref, ref, topic, event, _] = Phoenix.json_library().decode!(json_pkg)
%Phoenix.Socket.Message{
topic: topic,
event: event,
payload: my_data,
ref: ref,
join_ref: join_ref
}
else
[join_ref, ref, topic, event, payload | _] = Phoenix.json_library().decode!(iodata)
%Phoenix.Socket.Message{
topic: topic,
event: event,
payload: payload,
ref: ref,
join_ref: join_ref
}
end
end
def encode!(%Phoenix.Socket.Reply{} = reply) do
data = [
reply.join_ref,
reply.ref,
reply.topic,
"phx_reply",
%{status: reply.status, response: reply.payload}
]
{:socket_push, :binary, Phoenix.json_library().encode_to_iodata!(data)}
end
def encode!(%Phoenix.Socket.Message{} = msg) do
# I only boradcast message, so here only push system message
data = [msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload]
{:socket_push, :binary, Phoenix.json_library().encode_to_iodata!(data)}
end
def fastlane!(%Phoenix.Socket.Broadcast{} = msg) do
my_payload = Map.get(msg.payload, :payload)
empty_payload = %{}
data_empty = [nil, nil, msg.topic, msg.event, empty_payload]
data_b = Phoenix.json_library().encode_to_iodata!(data_empty)
data_buf = IO.iodata_to_binary(data_b)
data_size = byte_size(my_payload)
data_size_bs = <<data_size::size(32)>>
head = "{=+}"
pkg = <<head::bitstring, data_size_bs::bitstring, my_payload::bitstring, data_buf::binary>>
{:socket_push, :binary, pkg}
end