salvo-tus 0.89.3

TUS support for Salvo web framework
Documentation

Salvo is an extremely simple and powerful Rust web backend framework. Only basic Rust knowledge is required to develop backend services.

salvo-tus

TUS (Resumable Upload Protocol) implementation for the Salvo web framework. TUS is an open protocol for resumable file uploads over HTTP, allowing reliable uploads of large files by enabling pause and resume functionality.

Features

  • Resumable uploads: Clients can resume interrupted uploads from where they left off
  • Upload metadata: Attach custom metadata to uploads
  • Configurable max size: Limit upload file sizes with fixed or dynamic limits
  • Lifecycle hooks: React to upload events (create, finish, incoming request)
  • Custom upload IDs: Generate custom upload identifiers
  • Customizable storage: Use built-in disk storage or implement your own backend

Protocol Support

  • TUS protocol version: 1.0.0
  • Extensions: creation, creation-with-upload, creation-defer-length, termination
  • Built-in handlers: OPTIONS, POST, HEAD, PATCH, DELETE, GET

TUS Protocol Endpoints

Method Path Description
OPTIONS /uploads Returns TUS protocol capabilities
POST /uploads Creates a new upload
HEAD /uploads/{id} Returns upload progress
PATCH /uploads/{id} Uploads a chunk
DELETE /uploads/{id} Cancels an upload
GET /uploads/{id} Downloads the uploaded file

Installation

This is an official crate, so you can enable it in Cargo.toml:

salvo = { version = "*", features = ["tus"] }

Quick Start

use salvo::prelude::*;
use salvo::tus::{Tus, MaxSize};

#[tokio::main]
async fn main() {
    let tus = Tus::new()
        .path("/uploads")
        .max_size(MaxSize::Fixed(100 * 1024 * 1024));  // 100 MB limit

    let router = Router::new()
        .push(tus.into_router());

    let acceptor = TcpListener::new("0.0.0.0:8698").bind().await;
    Server::new(acceptor).serve(router).await;
}

Lifecycle Hooks

React to upload events:

let tus = Tus::new()
    .with_on_upload_create(|req, upload_info| async move {
        println!("New upload: {:?}", upload_info);
        Ok(UploadPatch::default())
    })
    .with_on_upload_finish(|req, upload_info| async move {
        println!("Upload complete: {:?}", upload_info);
        Ok(UploadFinishPatch::default())
    });

Storage Backends

By default, files are stored on disk using DiskStore. Implement the DataStore trait for custom storage (S3, database, etc.).

Documentation & Resources