-
-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
doc(socketio): factor-out repetitive documentation (#394)
- Loading branch information
Showing
18 changed files
with
562 additions
and
1,260 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Broadcast to all sockets without any filtering (except the current socket). | ||
If you want to include the current socket use emit operators from the [`io`] global context. | ||
|
||
[`io`]: crate::SocketIo | ||
|
||
# Example | ||
```rust | ||
# use socketioxide::{SocketIo, extract::*}; | ||
# use serde_json::Value; | ||
fn handler(io: SocketIo, socket: SocketRef, Data(data): Data::<Value>) { | ||
// This message will be broadcast to all sockets in this namespace except this one. | ||
socket.broadcast().emit("test", &data); | ||
// This message will be broadcast to all sockets in this namespace, including this one. | ||
io.emit("test", &data); | ||
} | ||
|
||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", |s: SocketRef| s.on("test", handler)); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Disconnect all sockets selected with the previous operators. | ||
|
||
# Example | ||
```rust | ||
# use socketioxide::{SocketIo, extract::*}; | ||
fn handler(socket: SocketRef) { | ||
// Disconnect all sockets in the room1 and room3 rooms, except for room2. | ||
socket.within("room1").within("room3").except("room2").disconnect().unwrap(); | ||
} | ||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", |s: SocketRef| s.on("test", handler)); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
# Emit a message to one or many clients | ||
|
||
If you provide tuple-like data (tuples, arrays), it will be considered as multiple arguments. | ||
Therefore, if you want to send an array as the _first_ argument of the payload, | ||
you need to wrap it in an array or a tuple. A [`Vec`] will always be considered a single argument. | ||
|
||
# Emitting binary data | ||
To emit binary data, you must use a data type that implements [`Serialize`] as binary data. | ||
Currently, if you use `Vec<u8>`, it will be considered a sequence of numbers rather than binary data. | ||
To handle this, you can either use a special type like [`Bytes`] or the [`serde_bytes`] crate. | ||
If you want to emit generic data that may contain binary, use [`rmpv::Value`] instead of | ||
[`serde_json::Value`], as binary data will otherwise be serialized as a sequence of numbers. | ||
|
||
# Errors | ||
* When encoding the data, a [`SendError::Serialize`] may be returned. | ||
* If the underlying engine.io connection is closed, a [`SendError::Socket(SocketError::Closed)`] | ||
will be returned, and the data you attempted to send will be included in the error. | ||
* If the packet buffer is full, a [`SendError::Socket(SocketError::InternalChannelFull)`] | ||
will be returned, and the data you attempted to send will be included in the error. | ||
See the [`SocketIoBuilder::max_buffer_size`] option for more information on internal buffer configuration. | ||
|
||
[`SocketIoBuilder::max_buffer_size`]: crate::SocketIoBuilder#method.max_buffer_size | ||
[`SendError::Serialize`]: crate::SendError::Serialize | ||
[`SendError::Socket(SocketError::Closed)`]: crate::SocketError::Closed | ||
[`SendError::Socket(SocketError::InternalChannelFull)`]: crate::SocketError::InternalChannelFull | ||
[`Bytes`]: bytes::Bytes | ||
[`serde_bytes`]: https://docs.rs/serde_bytes | ||
[`rmpv::Value`]: https://docs.rs/rmpv | ||
[`serde_json::Value`]: https://docs.rs/serde_json/latest/serde_json/value | ||
|
||
# Single-socket example | ||
```rust | ||
# use socketioxide::{SocketIo, extract::*}; | ||
# use serde_json::Value; | ||
# use std::sync::Arc; | ||
fn handler(socket: SocketRef, Data(data): Data::<Value>) { | ||
// Emit a test message to the client | ||
socket.emit("test", &data).ok(); | ||
// Emit a test message with multiple arguments to the client | ||
socket.emit("test", &("world", "hello", 1)).ok(); | ||
// Emit a test message with an array as the first argument | ||
let arr = [1, 2, 3, 4]; | ||
socket.emit("test", &[arr]).ok(); | ||
} | ||
|
||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", |socket: SocketRef| { | ||
socket.on("test", handler); | ||
}); | ||
``` | ||
|
||
# Single-socket binary example with the `bytes` crate | ||
```rust | ||
# use socketioxide::{SocketIo, extract::*}; | ||
# use serde_json::Value; | ||
# use std::sync::Arc; | ||
# use bytes::Bytes; | ||
fn handler(socket: SocketRef, Data(data): Data::<(String, Bytes, Bytes)>) { | ||
// Emit a test message to the client | ||
socket.emit("test", &data).ok(); | ||
// Emit a test message with multiple arguments to the client | ||
socket.emit("test", &("world", "hello", Bytes::from_static(&[1, 2, 3, 4]))).ok(); | ||
// Emit a test message with an array as the first argument | ||
let arr = [1, 2, 3, 4]; | ||
socket.emit("test", &[arr]).ok(); | ||
} | ||
|
||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", |socket: SocketRef| { | ||
socket.on("test", handler); | ||
}); | ||
``` | ||
|
||
# Broadcast example | ||
```rust | ||
# use socketioxide::{SocketIo, extract::*}; | ||
# use serde_json::Value; | ||
# use std::sync::Arc; | ||
# use bytes::Bytes; | ||
fn handler(socket: SocketRef, Data(data): Data::<(String, Bytes, Bytes)>) { | ||
// Emit a test message in the room1 and room3 rooms, except for room2, with the received binary payload | ||
socket.to("room1").to("room3").except("room2").emit("test", &data); | ||
|
||
// Emit a test message with multiple arguments to the client | ||
socket.to("room1").emit("test", &("world", "hello", 1)).ok(); | ||
|
||
// Emit a test message with an array as the first argument | ||
let arr = [1, 2, 3, 4]; | ||
socket.to("room2").emit("test", &[arr]).ok(); | ||
} | ||
|
||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", |s: SocketRef| s.on("test", handler)); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# Emit a message to the client and wait for one or more acknowledgments. | ||
|
||
See [`emit()`](#method.emit) for more details on emitting messages. | ||
|
||
The acknowledgment has a timeout specified in the config (5 seconds by default) | ||
(see [`SocketIoBuilder::ack_timeout`]) or can be set with the [`timeout()`](#method.timeout) operator. | ||
|
||
To receive acknowledgments, an [`AckStream`] is returned. It can be used in two ways: | ||
* As a [`Stream`]: This will yield all the acknowledgment responses, along with the corresponding socket ID, received from the client. This is useful when broadcasting to multiple sockets and expecting more than one acknowledgment. To get the socket from this ID, use [`io::get_socket()`]. | ||
* As a [`Future`]: This will yield the first acknowledgment response received from the client, useful when expecting only one acknowledgment. | ||
|
||
# Errors | ||
If packet encoding fails, an [`EncodeError`] is **immediately** returned. | ||
|
||
If the socket is full or if it is closed before receiving the acknowledgment, | ||
a [`SendError::Socket`] will be **immediately** returned, and the value to send will be given back. | ||
|
||
If the client does not respond before the timeout, the [`AckStream`] will yield | ||
an [`AckError::Timeout`]. If the data sent by the client is not deserializable as `V`, | ||
an [`AckError::Decode`] will be yielded. | ||
|
||
[`SocketIoBuilder::ack_timeout`]: crate::SocketIoBuilder#method.ack_timeout | ||
[`Stream`]: futures_core::stream::Stream | ||
[`Future`]: futures_core::future::Future | ||
[`AckError`]: crate::AckError | ||
[`AckError::Decode`]: crate::AckError::Decode | ||
[`AckError::Timeout`]: crate::AckError::Timeout | ||
[`AckError::Socket`]: crate::AckError::Socket | ||
[`AckError::Socket(SocketError::Closed)`]: crate::SocketError::Closed | ||
[`SendError::Socket`]: crate::SendError::Socket | ||
[`EncodeError`]: crate::EncodeError | ||
[`io::get_socket()`]: crate::SocketIo#method.get_socket | ||
|
||
# Single-socket example | ||
```rust | ||
# use socketioxide::{SocketIo, extract::*}; | ||
# use serde_json::Value; | ||
# use std::sync::Arc; | ||
async fn handler(socket: SocketRef, Data(data): Data::<Value>) { | ||
// Emit a test message and wait for an acknowledgment with the timeout specified in the global config | ||
match socket.emit_with_ack::<_, Value>("test", &data).unwrap().await { | ||
Ok(ack) => println!("Ack received {:?}", ack), | ||
Err(err) => println!("Ack error {:?}", err), | ||
} | ||
} | ||
|
||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", |socket: SocketRef| { | ||
socket.on("test", handler); | ||
}); | ||
``` | ||
|
||
# Single-socket example with custom acknowledgment timeout | ||
```rust | ||
# use socketioxide::{SocketIo, extract::*}; | ||
# use serde_json::Value; | ||
# use std::sync::Arc; | ||
# use tokio::time::Duration; | ||
async fn handler(socket: SocketRef, Data(data): Data::<Value>) { | ||
// Emit a test message and wait for an acknowledgment with the timeout specified here | ||
match socket.timeout(Duration::from_millis(2)).emit_with_ack::<_, Value>("test", &data).unwrap().await { | ||
Ok(ack) => println!("Ack received {:?}", ack), | ||
Err(err) => println!("Ack error {:?}", err), | ||
} | ||
} | ||
|
||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", |socket: SocketRef| { | ||
socket.on("test", handler); | ||
}); | ||
``` | ||
|
||
# Broadcast example | ||
```rust | ||
# use socketioxide::{SocketIo, extract::*}; | ||
# use serde_json::Value; | ||
# use futures_util::stream::StreamExt; | ||
async fn handler(socket: SocketRef, Data(data): Data::<Value>) { | ||
// Emit a test message in the room1 and room3 rooms, | ||
// except for room2, with the binary payload received | ||
let ack_stream = socket.to("room1") | ||
.to("room3") | ||
.except("room2") | ||
.emit_with_ack::<_, String>("message-back", &data) | ||
.unwrap(); | ||
ack_stream.for_each(|(id, ack)| async move { | ||
match ack { | ||
Ok(ack) => println!("Ack received, socket {} {:?}", id, ack), | ||
Err(err) => println!("Ack error, socket {} {:?}", id, err), | ||
} | ||
}).await; | ||
} | ||
|
||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", |s: SocketRef| s.on("test", handler)); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Filter out all sockets selected with the previous operators that are in the specified rooms. | ||
|
||
# Example | ||
```rust | ||
# use socketioxide::{SocketIo, extract::*}; | ||
# use serde_json::Value; | ||
fn handler(socket: SocketRef, Data(data): Data::<Value>) { | ||
// This message will be broadcast to all sockets in the namespace, | ||
// except for those in room1 and the current socket | ||
socket.broadcast().except("room1").emit("test", &data); | ||
} | ||
|
||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", |socket: SocketRef| { | ||
socket.on("register1", |s: SocketRef| s.join("room1").unwrap()); | ||
socket.on("register2", |s: SocketRef| s.join("room2").unwrap()); | ||
socket.on("test", handler); | ||
}); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Get a [`SocketRef`] by the specified [`Sid`]. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Add all sockets selected with the previous operators to the specified room(s). | ||
|
||
# Example | ||
```rust | ||
# use socketioxide::{SocketIo, extract::*}; | ||
fn handler(socket: SocketRef) { | ||
// Add all sockets that are in room1 and room3 to room4 and room5 | ||
socket.within("room1").within("room3").join(["room4", "room5"]).unwrap(); | ||
let sockets = socket.within("room4").within("room5").sockets().unwrap(); | ||
} | ||
|
||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", |s: SocketRef| s.on("test", handler)); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Remove all sockets selected with the previous operators from the specified room(s). | ||
|
||
# Example | ||
```rust | ||
# use socketioxide::{SocketIo, extract::*}; | ||
fn handler(socket: SocketRef) { | ||
// Remove all sockets that are in room1 and room3 from room4 and room5 | ||
socket.within("room1").within("room3").leave(["room4", "room5"]).unwrap(); | ||
let sockets = socket.within("room4").within("room5").sockets().unwrap(); | ||
} | ||
|
||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", |s: SocketRef| s.on("test", handler)); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Broadcast to all sockets only connected to this node. | ||
When using the default in-memory adapter, this operator is a no-op. | ||
|
||
# Example | ||
```rust | ||
# use socketioxide::{SocketIo, extract::*}; | ||
# use serde_json::Value; | ||
fn handler(socket: SocketRef, Data(data): Data::<Value>) { | ||
// This message will be broadcast to all sockets in this | ||
// namespace that are connected to this node | ||
socket.local().emit("test", &data); | ||
} | ||
|
||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", |s: SocketRef| s.on("test", handler)); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Get all room names in the current namespace. | ||
|
||
# Example | ||
```rust | ||
# use socketioxide::{SocketIo, extract::SocketRef}; | ||
fn handler(socket: SocketRef, io: SocketIo) { | ||
println!("Socket connected to the / namespace with id: {}", socket.id); | ||
let rooms = io.rooms().unwrap(); | ||
println!("All rooms in the / namespace: {:?}", rooms); | ||
} | ||
|
||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", handler); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Get all sockets selected with the previous operators. | ||
|
||
This can be used to retrieve any extension data (with the `extensions` feature enabled) from the sockets or to make certain sockets join other rooms. | ||
|
||
# Example | ||
```rust | ||
# use socketioxide::{SocketIo, extract::*}; | ||
fn handler(socket: SocketRef) { | ||
// Find extension data in each socket in the room1 and room3 rooms, except for room2 | ||
let sockets = socket.within("room1").within("room3").except("room2").sockets().unwrap(); | ||
for socket in sockets { | ||
println!("Socket custom string: {:?}", socket.extensions.get::<String>()); | ||
} | ||
} | ||
|
||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", |s: SocketRef| s.on("test", handler)); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Set a custom timeout when sending a message with an acknowledgement. | ||
|
||
* See [`SocketIoBuilder::ack_timeout`](crate::SocketIoBuilder) for the default timeout. | ||
* See [`emit_with_ack()`](#method.emit_with_ack) for more details on acknowledgements. | ||
|
||
# Example | ||
```rust | ||
# use socketioxide::{SocketIo, extract::*}; | ||
# use serde_json::Value; | ||
# use futures_util::stream::StreamExt; | ||
# use std::time::Duration; | ||
async fn handler(socket: SocketRef, Data(data): Data::<Value>) { | ||
// Emit a test message in the room1 and room3 rooms, except for the room2 | ||
// room with the binary payload received, and wait for 5 seconds for an acknowledgement | ||
socket.to("room1") | ||
.to("room3") | ||
.except("room2") | ||
.timeout(Duration::from_secs(5)) | ||
.emit_with_ack::<_, Value>("message-back", &data) | ||
.unwrap() | ||
.for_each(|(id, ack)| async move { | ||
match ack { | ||
Ok(ack) => println!("Ack received from socket {}: {:?}", id, ack), | ||
Err(err) => println!("Ack error from socket {}: {:?}", id, err), | ||
} | ||
}).await; | ||
} | ||
|
||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", |s: SocketRef| s.on("test", handler)); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Select all the sockets in the given rooms except for the current socket. | ||
|
||
When called from a socket, if you want to also include it, use the [`within()`](#method.within) operator. | ||
|
||
However, when called from the [`io`] (global context) level, there will be no difference. | ||
|
||
[`io`]: crate::SocketIo | ||
|
||
# Example | ||
```rust | ||
# use socketioxide::{SocketIo, extract::*}; | ||
# use serde_json::Value; | ||
async fn handler(socket: SocketRef, io: SocketIo, Data(data): Data::<Value>) { | ||
// Emit a message to all sockets in room1, room2, room3, and room4, except the current socket | ||
socket | ||
.to("room1") | ||
.to(["room2", "room3"]) | ||
.emit("test", &data); | ||
|
||
// Emit a message to all sockets in room1, room2, room3, and room4, including the current socket | ||
io | ||
.to("room1") | ||
.to(["room2", "room3"]) | ||
.emit("test", &data); | ||
} | ||
|
||
let (_, io) = SocketIo::new_svc(); | ||
io.ns("/", |s: SocketRef| s.on("test", handler)); | ||
``` |
Oops, something went wrong.