Rust backend
The plugin's client
init() puts a tauri_plugin_centrifugo::core::Centrifugo
into the managed state. The Tauri commands call it; your backend can too, and the frontend sees
the same client and the same events.
use tauri::Manager;
use tauri_plugin_centrifugo::core::Centrifugo;
use tauri_plugin_centrifugo::models::{PublishRequest, StartConfig, SubscribeOptions};
#[tauri::command]
async fn start_realtime(app: tauri::AppHandle, token: String) -> Result<(), String> {
let centrifugo = app.state::<Centrifugo>();
centrifugo
.connect(app.clone(), StartConfig {
url: "wss://example.com/connection/websocket".into(),
token: Some(token),
name: Some("my-app".into()),
version: None,
channels: vec!["news".into()],
use_protobuf: false,
read_timeout: Some(5000),
http_stream_url: None,
headers: None,
request_token: None,
})
.await
.map_err(|e| e.to_string())?;
let mut opts = SubscribeOptions::channel("chat:42");
opts.recoverable = Some(true);
centrifugo
.add_subscription_with_options(app.clone(), opts)
.await
.map_err(|e| e.to_string())
}
Every command has a method of the same name (publish, rpc, history, presence,
provide_token, …) taking the same request types from
models;
the request data is base64 or raw JSON as from JS (see Payloads). With
the base64 crate:
use base64::Engine;
centrifugo
.publish(PublishRequest {
channel: "news".into(),
data: base64::engine::general_purpose::STANDARD.encode(br#"{"text":"hi"}"#),
data_encoding: None,
r#type: None,
key: None,
removed: None,
})
.await?;
The functions in commands are public too
(tauri_plugin_centrifugo::commands::connect(window, config)); they take the Window and only
look up the state, so the managed state above is the shorter way.
Events reach Rust as well: listen to centrifugo:<event> with app.listen(...) (trait
tauri::Listener; the payload is the JSON described in Events). Token requests are answered with
provide_token / sub_refresh, from Rust or JS.
The SDK directly
The SDK the plugin is built on is re-exported as tauri_plugin_centrifugo::centrifuge, so a
backend can run its own client without adding it (for example a connection the webview should
not see). fetch_token stands for your own code; the stream needs futures-util:
use tauri_plugin_centrifugo::centrifuge::Client;
// build() takes the current Tokio runtime: run it inside Tauri's.
tauri::async_runtime::spawn(async move {
let client = Client::builder("wss://example.com/connection/websocket")
.get_token(|_ctx| async move { Ok(Some(fetch_token().await?)) })
.build()?;
let sub = client.new_subscription("news").recoverable(true).build()?;
let mut pubs = sub.publications();
sub.subscribe();
client.connect()?;
while let Some(p) = futures_util::StreamExt::next(&mut pubs).await {
println!("{}", String::from_utf8_lossy(&p.data));
}
Ok::<_, Box<dyn std::error::Error + Send + Sync>>(())
});
This client is separate from the plugin's: it emits no Tauri events. See the
centrifuge-client docs for its API. On Android give it the
same TLS setup as the plugin, see Android.