Guides

Rust backend

Use the plugin's client from Rust, or the centrifuge-client SDK directly.

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.

src-tauri/src/lib.rs
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.