#http #axum #cometd


Framework for CometD server creation

28 releases (8 breaking)

0.10.0 Feb 14, 2023
0.9.4 May 2, 2023
0.9.3 Mar 13, 2023
0.7.0-beta.3 Dec 21, 2022
0.3.0 Nov 30, 2022

#100 in #axum

Download history 30/week @ 2023-05-30 5/week @ 2023-06-06 2/week @ 2023-06-13 60/week @ 2023-06-20 4/week @ 2023-06-27 2/week @ 2023-07-04 2/week @ 2023-07-25 2/week @ 2023-08-01 4/week @ 2023-08-08 19/week @ 2023-08-15 48/week @ 2023-08-29 32/week @ 2023-09-05 1/week @ 2023-09-12

81 downloads per month



Rust 2K SLoC // 0.0% comments JavaScript 127 SLoC Shell 63 SLoC // 0.2% comments TypeScript 63 SLoC // 0.3% comments



This crate aims to make ability to use CometD protocol in servers written in Rust.

This project is in progress and might change a lot from version to version.

Table of contents

Server endpoints

Server have 4 endpoints:

  1. /handshake -- to register and get clientId;
  2. / -- to subscribe on channels;
  3. /connect -- to receiving or publish messages;
  4. /disconnect -- to say to server clean data for clientId;

You can change base part of these endpoints through RouterBuilder::handshake_base_path, RouterBuilder::subscribe_base_path, RouterBuilder::connect_base_path, RouterBuilder::disconnect_base_path. For example, to make /node/0/handshake and /node/1/connect you can do this:

use std::sync::Arc;
use axum_cometd::{LongPollingServiceContextBuilder, RouterBuilder};

let context = LongPollingServiceContextBuilder::new()

let router = RouterBuilder::new()

clientId and BAYEUX_BROWSER cookie

clientId and BAYEUX_BROWSER cookie is 40-character length hex string, with possibility of leading zeroes. Server will return '402::session_unknown' error if it will be not. To get some uniquity first 8 bytes is taken from Unix timestamp, and for randomness last part filled with random numbers.

How server works

BAYEUX_BROWSER cookie will be generated and set at /handshake request, if there isn't one already.

At others endpoints ([Server endpoints]) server check clientId and BAYEUX_BROWSER cookie (in case of publish messages to /connect it will be check each clientId). If clientId will be used with different BAYEUX_BROWSER cookie, server will return '402::session_unknown' error.

How get server events

Server have 3 events:

  1. Event::SessionAdded
  2. Event::Subscribe
  3. Event::SessionRemoved
  4. Event::CustomData

SessionAdded and Subscribe can contain additional data, which will be attached through axum::Extension. To get those events, you must use get receive channel LongPollingServiceContext::rx. Server do not use Event::CustomData, it user custom message which can be received in receiver.

use std::sync::Arc;
use axum::Extension;
use axum_cometd::{LongPollingServiceContextBuilder, RouterBuilder};

#[derive(Debug, Clone)]
struct ContextData {
    server_name: Arc<str>,

use std::time::Duration;
use axum_cometd::Event;
let context = LongPollingServiceContextBuilder::new()
    .build::<ContextData, &'static str>();

let app = RouterBuilder::new()
    .layer(Extension(ContextData {
        server_name: std::env::var("SERVER_NAME")
            .unwrap_or_else(|_| Arc::from("Skalica")),

let tx = context.tx();
let mut rx = context.rx();

tokio::task::spawn(async move {
    loop {

while let Some(event) = rx.recv().await {
    match *event {
            ref headers,
            ref data,
        } => {
            println!("sessionAdded with clientId({client_id}), headers({headers:?}), data({data:?})");
            ref headers,
            ref channels,
            ref data,
        } => {
            println!("subscribed on channels({channels:?}) with clientId({client_id}), headers({headers:?}), data({data:?})");
        } => println!("clientId({client_id}) session removed"),
        Event::CustomData(msg) => println!("got CustomData({msg})"),


~292K SLoC