fast-dav-rs is a high-performance asynchronous CalDAV client for Rust. It blends hyper 1.x, tokio, rustls,
and streaming XML tooling so your services can discover calendars, manage events, and keep remote CalDAV stores in sync
without re-implementing the protocol by hand.
- HTTP/2 with connection pooling, adaptive windows, and configurable timeouts.
- Automatic response decompression plus optional request compression (br, zstd, gzip).
- Streaming XML parsing for large
PROPFIND/REPORTresponses. - Convenience helpers for ETags, conditional methods, and safe deletions.
- First-class support for
REPORT calendar-query,calendar-multiget, WebDAV-Sync (RFC 6578), and bounded parallelism.
cargo add fast-dav-rsThe crate targets Rust 2024 and expects a multi-threaded tokio runtime with the macros, rt-multi-thread, and
time features enabled.
Discover calendars and list available collections:
use fast_dav_rs::CalDavClient;
use anyhow::Result;
#[tokio::main]
async fn main() -> Result<()> {
let client = CalDavClient::new(
"https://caldav.example.com/users/alice/",
Some("alice"),
Some("hunter2"),
)?;
let principal = client
.discover_current_user_principal()
.await?
.ok_or_else(|| anyhow::anyhow!("no principal returned"))?;
let homes = client.discover_calendar_home_set(&principal).await?;
let home = homes.first().expect("missing calendar-home-set");
for calendar in client.list_calendars(home).await? {
println!("Calendar: {:?}", calendar.displayname);
}
Ok(())
}- Create / update events:
put_if_none_matchandput_if_matchaccept ICS payloads and attach the proper conditional headers. - Filter collections:
calendar_query_timerangebuilds aREPORTto fetch events within a date range. - Safe deletion:
delete_if_matchensures you do not remove an event that changed on the server. - Batch work:
propfind_manyand themap_*helpers run multiple requests concurrently with bounded concurrency. - Compression: automatic negotiation eagerly probes gzip once and caches the result; override or disable it
through
RequestCompressionMode.
use fast_dav_rs::{CalDavClient, ContentEncoding, RequestCompressionMode};
use bytes::Bytes;
use anyhow::Result;
#[tokio::main]
async fn main() -> Result<()> {
let mut client = CalDavClient::new("https://caldav.example.com/users/alice/", None, None)?;
client.set_request_compression_mode(RequestCompressionMode::Force(ContentEncoding::Gzip));
let ics = Bytes::from_static(b"BEGIN:VCALENDAR\n...END:VCALENDAR\n");
client.put_if_none_match("work/calendar/event.ics", ics).await?;
let events = client
.calendar_query_timerange("work/calendar/", "VEVENT", None, None, true)
.await?;
for event in events {
println!("{} -> {:?}", event.href, event.etag);
}
Ok(())
}propfind_streamcombined withparse_multistatus_streamiterates a207 Multi-Statusresponse without buffering the entire payload.detect_encodingchooses the right decoder for compressed responses.supports_webdav_syncandsync_collectionlet you build incremental sync loops based on sync tokens rather than full scans.
cargo build— fast local compile.cargo fmt/cargo clippy --all-targets --all-features— mandatory formatting and linting before you push.cargo test --all-featuresandcargo test --doc— run unit, integration, and doctests to keep examples accurate../run-e2e-tests.sh— run end-to-end tests against a local SabreDAV server.
This project includes a complete E2E testing environment with a SabreDAV server that supports all major CalDAV features including compression.
- Docker and Docker Compose
- The SabreDAV test environment (located in
sabredav-test/)
cd sabredav-test
./setup.shThis will start a complete SabreDAV environment with:
- Nginx with gzip, Brotli, and zstd compression modules
- PHP-FPM for better performance
- MySQL database with preconfigured SabreDAV tables
- Test user (test/test) and sample calendar events
./run-e2e-tests.shOr manually:
cargo test --test caldav_suite -- e2e_tests --nocaptureTo reset the database to a clean state:
cd sabredav-test
./reset-db.shSee CONTRIBUTING.md for the standard workflow and AGENTS.md for repository-specific guidelines. Pull requests
improving server compatibility, ergonomics, or documentation are very welcome.