Readur/docs/webdav-enhanced-features.md

12 KiB

WebDAV Enhanced Features Documentation

This document describes the critical WebDAV features that have been implemented to provide comprehensive WebDAV protocol support.

Table of Contents

  1. WebDAV File Locking (LOCK/UNLOCK)
  2. Partial Content/Resume Support
  3. Directory Operations (MKCOL)
  4. Enhanced Status Code Handling

WebDAV File Locking

Overview

WebDAV locking prevents concurrent modification issues by allowing clients to lock resources before modifying them. This implementation supports both exclusive and shared locks with configurable timeouts.

Features

  • LOCK Method: Acquire exclusive or shared locks on resources
  • UNLOCK Method: Release previously acquired locks
  • Lock Tokens: Opaque lock tokens in the format opaquelocktoken:UUID
  • Lock Refresh: Extend lock timeout before expiration
  • Depth Support: Lock individual resources or entire directory trees
  • Automatic Cleanup: Expired locks are automatically removed

Usage

Acquiring a Lock

use readur::services::webdav::{WebDAVService, LockScope};

// Acquire an exclusive lock
let lock_info = service.lock_resource(
    "/documents/important.docx",
    LockScope::Exclusive,
    Some("user@example.com".to_string()), // owner
    Some(3600), // timeout in seconds
).await?;

println!("Lock token: {}", lock_info.token);

Checking Lock Status

// Check if a resource is locked
if service.is_locked("/documents/important.docx").await {
    println!("Resource is locked");
}

// Get all locks on a resource
let locks = service.get_lock_info("/documents/important.docx").await;
for lock in locks {
    println!("Lock: {} (expires: {:?})", lock.token, lock.expires_at);
}

Refreshing a Lock

// Refresh lock before it expires
let refreshed = service.refresh_lock(&lock_info.token, Some(7200)).await?;
println!("Lock extended until: {:?}", refreshed.expires_at);

Releasing a Lock

// Release the lock when done
service.unlock_resource("/documents/important.docx", &lock_info.token).await?;

Lock Types

  • Exclusive Lock: Only one client can hold an exclusive lock
  • Shared Lock: Multiple clients can hold shared locks simultaneously

Error Handling

  • 423 Locked: Resource is already locked by another process
  • 412 Precondition Failed: Lock token is invalid or expired
  • 409 Conflict: Lock conflicts with existing locks

Partial Content Support

Overview

Partial content support enables reliable downloads with resume capability, essential for large files or unreliable connections. The implementation follows RFC 7233 for HTTP Range Requests.

Features

  • Range Headers: Support for byte-range requests
  • 206 Partial Content: Handle partial content responses
  • Resume Capability: Continue interrupted downloads
  • Chunked Downloads: Download large files in manageable chunks
  • Progress Tracking: Monitor download progress in real-time

Usage

Downloading a Specific Range

use readur::services::webdav::ByteRange;

// Download bytes 0-1023 (first 1KB)
let chunk = service.download_file_range(
    "/videos/large_file.mp4",
    0,
    Some(1023)
).await?;

// Download from byte 1024 to end of file
let rest = service.download_file_range(
    "/videos/large_file.mp4",
    1024,
    None
).await?;

Download with Resume Support

use std::path::PathBuf;

// Download with automatic resume on failure
let local_path = PathBuf::from("/downloads/large_file.mp4");
let content = service.download_file_with_resume(
    "/videos/large_file.mp4",
    local_path
).await?;

Monitoring Download Progress

// Get progress of a specific download
if let Some(progress) = service.get_download_progress("/videos/large_file.mp4").await {
    println!("Downloaded: {} / {} bytes ({:.1}%)",
        progress.bytes_downloaded,
        progress.total_size,
        progress.percentage_complete()
    );
}

// List all active downloads
let downloads = service.list_active_downloads().await;
for download in downloads {
    println!("{}: {:.1}% complete", 
        download.resource_path,
        download.percentage_complete()
    );
}

Canceling a Download

// Cancel an active download
service.cancel_download("/videos/large_file.mp4").await?;

Range Format

  • bytes=0-1023 - First 1024 bytes
  • bytes=1024- - From byte 1024 to end
  • bytes=-500 - Last 500 bytes
  • bytes=0-500,1000-1500 - Multiple ranges

Directory Operations

Overview

Comprehensive directory management using WebDAV-specific methods, including the MKCOL method for creating collections (directories).

Features

  • MKCOL Method: Create directories with proper WebDAV semantics
  • Recursive Creation: Create entire directory trees
  • MOVE Method: Move or rename directories
  • COPY Method: Copy directories with depth control
  • DELETE Method: Delete directories recursively
  • Directory Properties: Set custom properties on directories

Usage

Creating Directories

use readur::services::webdav::CreateDirectoryOptions;

// Create a single directory
let result = service.create_directory(
    "/projects/new_project",
    CreateDirectoryOptions::default()
).await?;

// Create with parent directories
let options = CreateDirectoryOptions {
    create_parents: true,
    fail_if_exists: false,
    properties: None,
};
let result = service.create_directory(
    "/projects/2024/january/reports",
    options
).await?;

// Create entire path recursively
let results = service.create_directory_recursive(
    "/projects/2024/january/reports"
).await?;

Checking Directory Existence

if service.directory_exists("/projects/2024").await? {
    println!("Directory exists");
}

Listing Directory Contents

let contents = service.list_directory("/projects").await?;
for item in contents {
    println!("  {}", item);
}

Moving Directories

// Move (rename) a directory
service.move_directory(
    "/projects/old_name",
    "/projects/new_name",
    false // don't overwrite if exists
).await?;

Copying Directories

// Copy directory recursively
service.copy_directory(
    "/projects/template",
    "/projects/new_project",
    false, // don't overwrite
    Some("infinity") // recursive copy
).await?;

Deleting Directories

// Delete empty directory
service.delete_directory("/projects/old", false).await?;

// Delete directory and all contents
service.delete_directory("/projects/old", true).await?;

Status Code Handling

Overview

Enhanced error handling for WebDAV-specific status codes, providing detailed error information and automatic retry logic.

WebDAV Status Codes

Success Codes

  • 207 Multi-Status: Response contains multiple status codes
  • 208 Already Reported: Members already enumerated

Client Error Codes

  • 422 Unprocessable Entity: Request contains semantic errors
  • 423 Locked: Resource is locked
  • 424 Failed Dependency: Related operation failed

Server Error Codes

  • 507 Insufficient Storage: Server storage full
  • 508 Loop Detected: Infinite loop in request

Error Information

Each error includes:

  • Status code and description
  • Resource path affected
  • Lock token (if applicable)
  • Suggested resolution action
  • Retry information
  • Server-provided details

Usage

Enhanced Error Handling

use readur::services::webdav::StatusCodeHandler;

// Perform operation with enhanced error handling
let response = service.authenticated_request_enhanced(
    Method::GET,
    &url,
    None,
    None,
    &[200, 206] // expected status codes
).await?;

Smart Retry Logic

// Automatic retry with exponential backoff
let result = service.with_smart_retry(
    || Box::pin(async {
        // Your operation here
        service.download_file("/path/to/file").await
    }),
    3 // max attempts
).await?;

Error Details

match service.lock_resource(path, scope, owner, timeout).await {
    Ok(lock) => println!("Locked: {}", lock.token),
    Err(e) => {
        // Error includes WebDAV-specific information:
        // - Status code (e.g., 423)
        // - Lock owner information
        // - Suggested actions
        // - Retry recommendations
        println!("Lock failed: {}", e);
    }
}

Retry Strategy

The system automatically determines if errors are retryable:

Status Code Retryable Default Delay Backoff
423 Locked Yes 10s Exponential
429 Too Many Requests Yes 60s Exponential
503 Service Unavailable Yes 30s Exponential
409 Conflict Yes 5s Exponential
500-599 Server Errors Yes 30s Exponential
400-499 Client Errors No - -

Integration with Existing Code

All new features are fully integrated with the existing WebDAV service:

use readur::services::webdav::{
    WebDAVService, WebDAVConfig,
    LockManager, PartialContentManager,
    CreateDirectoryOptions, ByteRange,
    WebDAVStatusCode, WebDAVError
};

// Create service as usual
let config = WebDAVConfig { /* ... */ };
let service = WebDAVService::new(config)?;

// All new features are available through the service
// - Locking: service.lock_resource(), unlock_resource()
// - Partial: service.download_file_range(), download_file_with_resume()
// - Directories: service.create_directory(), delete_directory()
// - Errors: Automatic enhanced error handling

Testing

All features include comprehensive test coverage:

# Run all tests
cargo test --lib

# Run specific feature tests
cargo test locking_tests
cargo test partial_content_tests
cargo test directory_ops_tests

# Run integration tests (requires WebDAV server)
cargo test --ignored

Performance Considerations

  1. Lock Management: Locks are stored in memory with automatic cleanup of expired locks
  2. Partial Downloads: Configurable chunk size (default 1MB) for optimal performance
  3. Directory Operations: Batch operations use concurrent processing with semaphore control
  4. Error Handling: Smart retry with exponential backoff prevents server overload

Security Considerations

  1. Lock Tokens: Use cryptographically secure UUIDs
  2. Authentication: All operations use HTTP Basic Auth (configure HTTPS in production)
  3. Timeouts: Configurable timeouts prevent resource exhaustion
  4. Rate Limiting: Respect server rate limits with automatic backoff

Compatibility

The implementation follows these standards:

  • RFC 4918 (WebDAV)
  • RFC 7233 (HTTP Range Requests)
  • RFC 2518 (WebDAV Locking)

Tested with:

  • Nextcloud
  • ownCloud
  • Apache mod_dav
  • Generic WebDAV servers

Migration Guide

For existing code using the WebDAV service:

  1. No Breaking Changes: All existing methods continue to work
  2. New Features Are Opt-In: Use new methods only when needed
  3. Enhanced Error Information: Errors now include more details but maintain backward compatibility
  4. Automatic Benefits: Some improvements (like better error handling) apply automatically

Troubleshooting

Lock Issues

  • 423 Locked Error: Another client holds a lock. Wait or use lock token
  • Lock Token Invalid: Lock may have expired. Acquire a new lock
  • Locks Not Released: Implement proper cleanup in error paths

Partial Content Issues

  • Server Doesn't Support Ranges: Falls back to full download automatically
  • Resume Fails: File may have changed. Restart download
  • Slow Performance: Adjust chunk size based on network conditions

Directory Operation Issues

  • 409 Conflict: Parent directory doesn't exist. Use create_parents: true
  • 405 Method Not Allowed: Directory may already exist or server doesn't support MKCOL
  • 507 Insufficient Storage: Server storage full. Contact administrator

Future Enhancements

Potential future improvements:

  • WebDAV SEARCH method support
  • Advanced property management (PROPPATCH)
  • Access control (WebDAV ACL)
  • Versioning support (DeltaV)
  • Collection synchronization (WebDAV Sync)