Skip to content

Commit

Permalink
Fix the implementation for the multi payload (#392)
Browse files Browse the repository at this point in the history
feat: Implement multi payload
  • Loading branch information
shenjackyuanjie authored Apr 11, 2024
1 parent decb053 commit 2636b23
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 46 deletions.
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions ci/socket-io.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ var callback = client => {
client.emit('This is the first argument', 'This is the second argument', {
argCount: 3
});
client.emit('on_abc_event', '', {
abc: 0,
some_other: 'value',
});
};
io.on('connection', callback);
io.of('/admin').on('connection', callback);
Expand Down
1 change: 0 additions & 1 deletion engineio/src/packet.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
extern crate base64;
use base64::{engine::general_purpose, Engine as _};
use bytes::{BufMut, Bytes, BytesMut};
use serde::{Deserialize, Serialize};
Expand Down
56 changes: 40 additions & 16 deletions socketio/src/asynchronous/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,29 +461,26 @@ impl Client {
};

// a socketio message always comes in one of the following two flavors (both JSON):
// 1: `["event", "msg"]`
// 1: `["event", "msg", ...]`
// 2: `["msg"]`
// in case 2, the message is ment for the default message event, in case 1 the event
// is specified
if let Ok(Value::Array(contents)) = serde_json::from_str::<Value>(data) {
let (event, data) = if contents.len() > 1 {
// case 1
let event = match contents.first() {
Some(Value::String(ev)) => Event::from(ev.as_str()),
_ => Event::Message,
};

(event, contents.get(1).ok_or(Error::IncompletePacket())?)
} else {
// case 2
(
Event::Message,
contents.first().ok_or(Error::IncompletePacket())?,
)
let (event, payloads) = match contents.len() {
0 => return Err(Error::IncompletePacket()),
// Incorrect packet, ignore it
1 => (Event::Message, contents.as_slice()),
// it's a message event
_ => match contents.first() {
Some(Value::String(ev)) => (Event::from(ev.as_str()), &contents[1..]),
// get rest(1..) of them as data, not just take the 2nd element
_ => (Event::Message, contents.as_slice()),
// take them all as data
},
};

// call the correct callback
self.callback(&event, data.to_string()).await?;
self.callback(&event, payloads.to_vec()).await?;
}

Ok(())
Expand Down Expand Up @@ -1067,6 +1064,33 @@ mod test {
)
);

let packet: Option<Packet> = Some(socket_stream.next().await.unwrap()?);

assert!(packet.is_some());

let packet = packet.unwrap();
assert_eq!(
packet,
Packet::new(
PacketId::Event,
nsp.clone(),
Some(
serde_json::json!([
"on_abc_event",
"",
{
"abc": 0,
"some_other": "value",
}
])
.to_string()
),
None,
0,
None,
)
);

let cb = |message: Payload, _| {
async {
println!("Yehaa! My ack got acked?");
Expand Down
64 changes: 43 additions & 21 deletions socketio/src/client/raw_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,14 +288,13 @@ impl RawClient {
}

if let Some(ref attachments) = socket_packet.attachments {
if let Some(payload) = attachments.get(0) {
if let Some(payload) = attachments.first() {
ack.callback.deref_mut()(Payload::Binary(payload.to_owned()), self.clone());
}
}
} else {
// Do something with timed out acks?
}

// nope, just ignore it, the official implment just remove the ack id when timeout
// https://github.com/socketio/socket.io-client/blob/main/lib/socket.ts#L467-L495
false
});

Expand All @@ -312,7 +311,7 @@ impl RawClient {
};

if let Some(attachments) = &packet.attachments {
if let Some(binary_payload) = attachments.get(0) {
if let Some(binary_payload) = attachments.first() {
self.callback(&event, Payload::Binary(binary_payload.to_owned()))?;
}
}
Expand All @@ -327,29 +326,25 @@ impl RawClient {
};

// a socketio message always comes in one of the following two flavors (both JSON):
// 1: `["event", "msg"]`
// 1: `["event", "msg", ...]`
// 2: `["msg"]`
// in case 2, the message is ment for the default message event, in case 1 the event
// is specified
if let Ok(Value::Array(contents)) = serde_json::from_str::<Value>(data) {
let (event, data) = if contents.len() > 1 {
// case 1
let event = match contents.first() {
Some(Value::String(ev)) => Event::from(ev.as_str()),
_ => Event::Message,
};

(event, contents.get(1).ok_or(Error::IncompletePacket())?)
} else {
// case 2
(
Event::Message,
contents.first().ok_or(Error::IncompletePacket())?,
)
let (event, payloads) = match contents.len() {
0 => return Err(Error::IncompletePacket()),
1 => (Event::Message, contents.as_slice()),
// get rest of data if first is a event
_ => match contents.first() {
Some(Value::String(ev)) => (Event::from(ev.as_str()), &contents[1..]),
// get rest(1..) of them as data, not just take the 2nd element
_ => (Event::Message, contents.as_slice()),
// take them all as data
},
};

// call the correct callback
self.callback(&event, data.to_string())?;
self.callback(&event, payloads.to_vec())?;
}

Ok(())
Expand Down Expand Up @@ -751,6 +746,33 @@ mod test {
)
);

let packet: Option<Packet> = iter.next();

assert!(packet.is_some());

let packet = packet.unwrap();
assert_eq!(
packet,
Packet::new(
PacketId::Event,
nsp.clone(),
Some(
serde_json::json!([
"on_abc_event",
"",
{
"abc": 0,
"some_other": "value",
}
])
.to_string()
),
None,
0,
None,
)
);

assert!(socket
.emit_with_ack(
"test",
Expand Down

0 comments on commit 2636b23

Please sign in to comment.