Skip to content

Goopil/fast-dav-rs

Repository files navigation

fast-dav-rs

Crates.io Documentation CI

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.

Highlights

  • 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/REPORT responses.
  • 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.

Install

cargo add fast-dav-rs

The crate targets Rust 2024 and expects a multi-threaded tokio runtime with the macros, rt-multi-thread, and time features enabled.

Quick Start

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(())
}

Common Operations

  • Create / update events: put_if_none_match and put_if_match accept ICS payloads and attach the proper conditional headers.
  • Filter collections: calendar_query_timerange builds a REPORT to fetch events within a date range.
  • Safe deletion: delete_if_match ensures you do not remove an event that changed on the server.
  • Batch work: propfind_many and the map_* 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(())
}

Streaming & Sync

  • propfind_stream combined with parse_multistatus_stream iterates a 207 Multi-Status response without buffering the entire payload.
  • detect_encoding chooses the right decoder for compressed responses.
  • supports_webdav_sync and sync_collection let you build incremental sync loops based on sync tokens rather than full scans.

Development Commands

  • cargo build — fast local compile.
  • cargo fmt / cargo clippy --all-targets --all-features — mandatory formatting and linting before you push.
  • cargo test --all-features and cargo 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.

End-to-End Testing

This project includes a complete E2E testing environment with a SabreDAV server that supports all major CalDAV features including compression.

Prerequisites

  1. Docker and Docker Compose
  2. The SabreDAV test environment (located in sabredav-test/)

Setting up the Test Environment

cd sabredav-test
./setup.sh

This 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

Running E2E Tests

./run-e2e-tests.sh

Or manually:

cargo test --test caldav_suite -- e2e_tests --nocapture

Resetting the Test Environment

To reset the database to a clean state:

cd sabredav-test
./reset-db.sh

See CONTRIBUTING.md for the standard workflow and AGENTS.md for repository-specific guidelines. Pull requests improving server compatibility, ergonomics, or documentation are very welcome.

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

No packages published

Languages