fileloft-core 0.1.0

Framework-agnostic core for the tus.io resumable upload protocol
Documentation

fileloft

fileloft is a Rust implementation of the tus resumable upload protocol. It ships as a small set of composable crates you can embed in an existing HTTP server, or run as a standalone tus endpoint via the published container image.

  • Framework agnostic — protocol core with no transport assumptions, plus adapters for Axum, Actix Web, and Rocket.
  • Pluggable storage — a DataStore trait with in-memory and filesystem backends; bring your own for object storage or other backends.
  • Standalone or embedded — use it as a library or run the prebuilt image when you only need a tus endpoint.
  • Safe by default#![forbid(unsafe_code)] across the workspace, with conservative defaults for limits, locking, and checksums.

Crates: fileloft-core, fileloft-store-memory, fileloft-store-fs, fileloft-axum, fileloft-actix, fileloft-rocket.

Getting started

Use as a library (Axum)

Add dependencies (versions should match what you use elsewhere; see crates.io):

[dependencies]
fileloft-core         = "0.1"
fileloft-store-fs     = "0.1"
fileloft-axum         = "0.1"   # or fileloft-actix / fileloft-rocket
tokio                 = { version = "1", features = ["full"] }

Mount a tus router (other adapters follow the same pattern: build a TusHandler, then use the framework-specific router):

use std::sync::Arc;

use fileloft_axum::tus_router;
use fileloft_core::{Config, TusHandler};
use fileloft_store_fs::{FileLocker, FileStore};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    let root = "/var/lib/fileloft";
    let store = FileStore::new(root);
    let locker = FileLocker::new(format!("{root}/locks"));
    let handler = Arc::new(TusHandler::new(store, Some(locker), Config::default()));

    let app = axum::Router::new().nest("/files", tus_router(handler));

    let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await?;
    axum::serve(listener, app).await?;
    Ok(())
}

Full tus 1.0.0 core plus optional extensions (creation, expiration, checksum, termination, concatenation) are configured via Config. API details: docs.rs/fileloft-core.

Run the container

docker run --rm \
  -p 8080:8080 \
  -v fileloft-data:/var/lib/fileloft \
  ghcr.io/sound-systems/fileloft:latest

The server listens on :8080 and stores data under /var/lib/fileloft. Common environment overrides:

Variable Default Description
FILELOFT_BIND 0.0.0.0:8080 Address the HTTP server binds to.
FILELOFT_DATA_DIR /var/lib/fileloft Directory used by the filesystem store.
FILELOFT_MAX_SIZE unset Maximum allowed upload size, in bytes.
FILELOFT_BASE_PATH /files Path the tus endpoints are mounted under.

More detail lives in the Hugo site under docs-site.

Quick health check with any tus 1.0.0 client:

curl -i -X POST http://localhost:8080/files \
  -H "Tus-Resumable: 1.0.0" \
  -H "Upload-Length: 11" \
  -H "Upload-Metadata: filename aGVsbG8udHh0"

A 201 Created response with a Location header indicates the endpoint is ready.

Build and test from this repository

cargo test --workspace

The Hugo documentation site lives under docs-site; build it with:

cd docs-site && hugo --minify

Contributing

  • Issues and PRs — open an issue to discuss larger changes; pull requests are welcome for fixes and improvements that match the project’s scope (tus protocol implementation, adapters, and stores).
  • Checks — before submitting, run cargo fmt --all, cargo clippy --workspace --all-targets, and cargo test --workspace so CI stays green. This repo pins a Rust toolchain with rustfmt and clippy in rust-toolchain.toml.
  • Style — follow existing patterns in the crate you touch; the workspace forbids unsafe_code. Prefer explicit error handling over panicking in library and application code.
  • Documentation — user-facing behavior worth explaining should be reflected in crate docs or the docs-site content when it affects how people integrate or operate fileloft.

Licensed under the MIT license (see crate metadata).