Skip to main content

Crate rustango

Crate rustango 

Source
Expand description

rustango — a batteries-included web framework for Rust.

It is built on one derive macro and one connection type, and ships a typed ORM with auto-migrations, an auto-generated admin, multi-tenancy, auth (sessions / JWT / OAuth2-OIDC / HMAC / passkeys), serializers and viewsets, signals, caching, media, email, background jobs, scheduled tasks, OpenAPI 3.1, and the usual production middleware.

Postgres, MySQL and SQLite all use the same sql::Pool and the same #[derive(Model)] types. The backend is a Cargo feature, not a rewrite.

Everything is opt-in: take only the features you use, down to the bare ORM with no HTTP stack. Release history is in the CHANGELOG.

§Install

[dependencies]
rustango = "0.61"                                        # Postgres (the default backend)
# or pick another backend — see "Choosing a backend" below:
rustango = { version = "0.61", default-features = false, features = ["sqlite", "batteries"] }
rustango = { version = "0.61", default-features = false, features = ["mysql",  "batteries"] }

default = ["postgres", "batteries"]. batteries is everything except the backend (admin, serializers, auth, jobs, cache, media, middleware, …). You pick the backend separately, so you can keep the batteries and still choose your database. Drop batteries for the bare ORM (no axum, no Tera).

§A taste

ⓘ
use rustango::Model;
use rustango::sql::{Auto, Pool, FetcherPool};

// One derive gives a table, typed columns, migrations, and admin wiring.
#[derive(Model, Clone, Debug)]
#[rustango(table = "posts")]
struct Post {
    #[rustango(primary_key)]
    id: Auto<i64>,                 // server-assigned auto-increment PK
    #[rustango(max_length = 200)]
    title: String,
    body: String,
    published: bool,
}

// One connection type for every backend — the driver is chosen from the
// URL scheme (postgres://…, mysql://…, sqlite://…).
let pool = Pool::connect(&std::env::var("DATABASE_URL")?).await?;

// Chained queries, compiled to your dialect.
let recent: Vec<Post> = Post::objects()
    .filter("published", true)
    .order_by_desc("id")
    .limit(10)
    .fetch(&pool)
    .await?;

§Choosing a backend

The same models and queries emit Postgres, MySQL or SQLite SQL. You pick the backend with a Cargo feature and the DATABASE_URL scheme.

  • Connect with sql::Pool::connect. It reads the URL scheme and builds the right pool. Prefer it over sqlx::PgPool::connect(...), which only exists when the postgres feature is on.
  • sql::Pool is the enum every rustango API takes (&Pool). A concrete sqlx::PgPool / SqlitePool / MySqlPool converts into it with From, so you can pass either.
  • Enable one backend feature (postgres, mysql, or sqlite) for a single-database app. Enable several to build one binary that serves any of them.
  • Multi-tenancy works on all three: tenancy::TenantPools is generic over the backend. Schema-mode tenancy is Postgres-only, because it uses SET search_path.

§Feature flags

FeatureGives you
postgres / mysql / sqliteThe database backend(s).
batteriesThe default bundle minus the backend (see Install).
adminAuto-generated admin UI + session auth; #[derive(ViewSet)] REST endpoints (also under tenancy).
tenancyMulti-tenant resolver, per-tenant pools, operator console.
serializer#[derive(Serializer)] JSON serializers.
jwt / oauth2Token auth; social / OIDC login.
jobs / jobs-postgresBackground jobs (in-memory / durable).
cache / cache-redisCache layer; Redis backend.
storage / storage-s3 / storage-azure / mediaFile storage + the Media model.
mcpModel Context Protocol server over HTTP.
openapiOpenAPI 3.1 schema auto-derive.

Every feature is listed in the crate’s Cargo.toml with a one-line note.

§Quick start (scaffolder)

cargo install cargo-rustango
cargo rustango new myblog                 # default: ORM + admin
cargo rustango new myapi --template api   # JSON-only, no admin
cargo rustango new shop --template tenant # multi-tenancy + operator console

cd myblog
cp .env.example .env                      # set DATABASE_URL
cargo run -- migrate                      # apply bootstrap migrations
cargo run                                 # http://localhost:8080

§The manage runner

One binary serves HTTP and dispatches CLI commands: cargo run starts the server, cargo run -- <verb> runs a command. A scaffolded main.rs:

ⓘ
#[rustango::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let _ = dotenvy::dotenv();
    rustango::manage::Cli::new()
        .api(myblog::urls::api())
        .tenancy()                         // optional, with the `tenancy` feature
        .run()
        .await
}

Common verbs (each supports --help):

GroupVerbs
Migrationsmakemigrations, migrate [target], downgrade [N], showmigrations
Scaffoldersstartapp, make:viewset, make:serializer, make:form, make:job, make:middleware, make:test
Systemabout, check, check --deploy, version
Tenancycreate-tenant, create-operator, create-user, list-tenants, create-api-key, grant-perm, audit-cleanup

§Where to look

The workspace README has the full feature matrix and guides. examples/cookbook_blog is a runnable multi-tenant blog with one chapter per feature.

Re-exports§

pub use sql::Auto;
pub use rustango_macros as macros;

Modules§

access_log
HTTP access log middleware — one tracing event per request with method / path / status / duration / IP. See access_log::AccessLogLayer. HTTP access log middleware — emit one tracing event per request.
account_lockout
Per-account login lockout — defends against credential stuffing. Cache-backed counter + lock flag. See account_lockout::Lockout. Per-account login lockout. Stops credential stuffing and brute force that gets past per-IP rate limits.
admin
Auto-generated CRUD admin for rustango models.
api_errors
Standardized API error responses. See api_errors::ApiError. Needs only axum, so every HTTP surface can answer in this shape. One JSON shape for every API error, so clients can parse them all the same way. It follows RFC 7807 “Problem Details” loosely:
api_keys
Generic API key generation + verification (argon2id-hashed). See api_keys::generate_key / api_keys::verify_key. Create and check API keys.
api_version
API versioning — extract version from header / query / URL prefix. See api_version::VersionStrategy and api_version::ApiVersion. Read the requested API version from the URL, a header or a query parameter.
audit
Audit log — one table that records every tracked write (insert, update, delete, soft-delete) for models declared with #[rustango(audit(...))].
auth_backends
Pluggable AUTHENTICATION_BACKENDS chain — register an ordered list of auth_backends::AuthBackend impls; the chain returns the first non-None result. Ships RemoteUserBackend for SSO proxy setups. A chain of authentication backends, tried in order.
auth_decorators
Access gates — login_required middleware and ?next= round-trip helpers. Access gates: login_required middleware and ?next= round-trip helpers.
auth_flows
Pre-built auth flows — password reset, email verification, magic-link login. See auth_flows::PasswordReset / auth_flows::EmailVerification. Pre-built auth flows — password reset + email verification.
base36
Base36 integer encoding — used in password reset URLs and other URL-friendly opaque IDs. int_to_base36(n) + base36_to_int(s) round-trip. Base36 integer encoding: int_to_base36 / base36_to_int.
base62
Base62 integer encoding — the [0-9A-Za-z] alphabet, for short URL IDs. Like base36 but case-sensitive, so 6 bits per character. Base62 integer encoding: int_to_base62 / base62_to_int.
body_limit
Request body size limit middleware — fast Content-Length rejection returning structured 413 Payload Too Large JSON. Replaces axum’s per-extractor DefaultBodyLimit. See body_limit::BodyLimitLayer. Request body size limit middleware.
bulk_actions
Bulk-action runner — apply one operation to a set of selected PKs. Works on all three backends. See bulk_actions::BulkActionRegistry and the built-in actions. Pluggable bulk actions for the auto-admin — the “Action” dropdown above a list view.
cache
Pluggable caching layer — cache::Cache trait + cache::NullCache + cache::InMemoryCache. Redis backend behind the cache-redis feature. Pluggable caching layer.
cache_fragment
Fragment caching — cache one rendered piece of a page. cache_fragment::cached_render checks the cache before it calls your compute closure. It is a handler-side helper rather than a Tera block tag, because Tera has no block-tag extension API. Fragment caching: cache one rendered piece of a page.
cache_page
Per-view caching tower layer + Cache-Control / Vary header builders. Caches a whole successful response and serves it again. Per-view caching: cache a whole successful response, plus Cache-Control and Vary header builders.
casts
Attribute casts — Cast<C> field wrapper + CastValue trait, with the EncryptedString AEAD-at-rest built-in. Transform a field on its way to and from the database.
composite_pk
Composite-primary-key patterns — a multi-column key expressed as an Auto<i64> surrogate plus unique_together. See composite_pk. How to model a key made of several columns — an order line identified by (order_id, line_no), say.
compression
Response compression middleware — gzip and deflate. Honors Accept-Encoding and skips bodies that are already compressed. See compression::CompressionLayer. Response compression middleware: gzip and deflate.
config
Layered TOML configuration.
content_negotiation
HTTP content negotiation — pick the best response format from the client’s Accept header. See content_negotiation::negotiate. Pick a response format from the client’s Accept header.
contenttypes
ContentType framework — a runtime handle for “any registered model”. Used by permissions, generic foreign keys, soft-FK prefetch and audit-history admin panels. The ContentType framework.
cookies
Set-Cookie builder — Cookie::new(name, value) .path("/").max_age(secs).http_only().secure().same_site(...).build() returns an axum-ready HeaderValue. Use it instead of writing cookie strings by hand. A Set-Cookie builder, plus a parser for a Cookie: header.
core
Core types for rustango.
cors
CORS middleware — cors::CorsLayer for axum routers. CORS middleware — Cross-Origin Resource Sharing for axum routers.
csp_nonce
Per-request CSP nonce middleware — makes a fresh random nonce per request, exposes it as Extension<Nonce>, and replaces 'nonce-__RUSTANGO_NONCE__' in the CSP header, so inline <script nonce="..."> tags pass a strict CSP. See csp_nonce::CspNonceLayer. Built with admin too: [security] mounts it so the bundled admin pages pass a strict CSP (#1703). Per-request CSP nonce middleware.
csv
Minimal RFC 4180 CSV writer — zero deps. See csv::CsvWriter. Small CSV writer. Follows RFC 4180 and pulls in no dependencies.
csv_response
axum response wrapper for CSV exports — sets Content-Type + optional Content-Disposition so browsers prompt a “Save as…” download. See csv_response::CsvResponse. A CSV download response. It sets Content-Type and, when you give a filename, a Content-Disposition that makes the browser offer a “Save as” dialog.
databases
Named multi-database registry + QuerySet::using(alias). A registry of named databases, plus QuerySet::using(alias) to route a query to one of them.
dateformat
Date format-character expander — turns a template format string such as {{ obj|date:"Y-m-d H:i" }} into the matching output. Template-style date format codes.
dateparse
ISO 8601 date / time / datetime / duration parsers — dateparse::{parse_date, parse_time, parse_datetime, parse_duration}. ISO 8601 / W3C date and time parsers.
dates
Month / weekday name lookups — month_full(m), month_abbr(m), month_ap(m), weekday_full(d), weekday_abbr(d). English-only by design (i18n is a separate concern). English month and weekday names.
dbshell
manage dbshell — spawn psql / mysql / sqlite3 for the current DATABASE_URL. manage dbshell: open the native CLI client for the current DATABASE_URL.
debug_panel
Debug profiling panel at /__debug__/ — Telescope/Debug-Toolbar-shape. DEV ONLY — captures per-request telemetry. See debug_panel. Debug profiling panel — /__debug__/ for development.
default_filters
Everyday template filters — pluralize, truncatewords, linebreaks, default_if_none. See default_filters. Everyday template filters, registered on Tera.
distributed_lock
Distributed locks backed by cache::Cache — only one worker runs a task at a time. A TTL recovers the lock after a crash, and release is token-checked. See distributed_lock::DistributedLock. Distributed locks backed by Cache.
email
Email backends — email::Mailer trait + console/in-memory/null backends. Email backend layer — pluggable async email sending.
email_jobs
Send email off the request path through the crate::jobs queue, so a temporary SMTP failure retries instead of failing the handler. See email_jobs::register_email_job + email_jobs::dispatch_email. Send email off the request path via the crate::jobs queue.
email_templates
Tera-rendered email helpers — bridge crate::email mailers and the Tera templating engine. Each email = <name>.subject.txt + <name>.txt + optional <name>.html. See email_templates::EmailRenderer. Tera-rendered emails: joins the crate::email mailer to the Tera template engine.
env
Typed environment variable readers — required / with_default / optional / list / duration_secs / duration_millis. Typed readers for environment variables.
errors
HTML error pages: the errors::Message extension, and (with template_views) the layer that dresses 4xx/5xx responses. HTML error pages: one layer that dresses every 4xx/5xx of an app.
etag
ETag middleware — hashes 2xx response bodies, returns 304 when If-None-Match matches. See etag::EtagLayer. ETag middleware — hashes response bodies and serves 304 Not Modified when the client’s If-None-Match matches.
events
Domain event bus — typed pub-sub for application events, separate from the ORM. Use it for cross-component fan-out (OrderPlaced → mail + billing + audit). For per-model lifecycle hooks use signals instead. See events::EventBus. Domain event bus: typed pub-sub for application events, separate from the ORM.
extractors
Per-request extractors for handlers — tenancy-aware DI. Ships extractors::Tenant, extractors::SessionUser, and extractors::SessionOperator. Tenancy-aware extractors for handlers.
feature_flags
Feature flags / killswitches backed by cache::Cache — boolean killswitch + per-user override + stable percentage rollout. See feature_flags::FeatureFlags. Feature flags backed by the Cache trait.
fixtures
Test fixture loader — seed a database from JSON files. See fixtures::Fixture. Test fixture loader — seed a test database from JSON files.
flatpages
Static “flat pages” — about, terms, privacy. Build a flatpages::FlatPageMap (path → flatpages::FlatPage) and mount flatpages::flatpages_middleware. A matching request serves the page body as text/html, or a content-type you choose. Tera wrapping is up to you. Static “flat pages” — about, terms, privacy.
forms
Form parsing, validation, and saving — shared between the auto-admin and user route handlers.
health
Health check endpoints — /health (liveness) + /ready (readiness). See health::health_router. Health check endpoints — /health (liveness) and /ready (readiness).
hmac_auth
AWS-style canonical request signed with SHA-256, replay-bounded by an X-Date tolerance window. See hmac_auth::HmacAuthLayer. HMAC-signed request authentication for service-to-service traffic.
host_validation
Host-header allowlist middleware — refuses a request whose Host is not on the list. See host_validation::AllowedHostsLayer. Host-header allowlist middleware.
http_client
Opinionated HTTP client — reqwest wrapper with sane timeouts, retry on idempotent verbs / transient failures, default User-Agent. See http_client::HttpClient. HTTP client: a reqwest wrapper with sane timeouts, backoff retries and a default User-Agent.
http_date
HTTP date parser and formatter — reads RFC 1123, RFC 850 and asctime forms per RFC 7231; writes IMF-fixdate. http_date::http_date(secs) + parse_http_date(s). HTTP date parser and formatter.
http_methods
Per-route HTTP method allowlists as tower middleware — require_GET, require_POST, require_safe. A method that is not allowed gets 405 Method Not Allowed with an Allow: header listing the rest. HTTP method restriction layer — require_methods, require_get, require_post, require_safe.
http_query
HTTP QUERY method routing (RFC 10008) — query(handler) and .query() chaining on axum’s MethodRouter. See http_query::QueryRouterExt. Routing for the HTTP QUERY method (RFC 10008).
humanize
Human-readable template filters — intcomma, intword, naturalsize, ordinal, apnumber, naturaltime, naturalday. See humanize. Human-readable number, size and time filters for Tera.
i18n
Internationalization (i18n) — translation lookups + Accept-Language negotiation. See i18n::Translator and i18n::negotiate_language. Internationalization (i18n) — translation lookups + Accept-Language negotiation.
idempotency
Idempotency-key middleware (Stripe-shape) — replays a stored successful response when a write request arrives with the same Idempotency-Key. Backed by any cache::Cache. See idempotency::IdempotencyLayer. Idempotency-key middleware, in the shape Stripe uses.
inheritance
Model-inheritance patterns — how to share fields between models: abstract bases, multi-table and proxy shapes. See inheritance. Model-inheritance patterns: how to share fields and behaviour between models.
ip_filter
IP allowlist / blocklist middleware. See ip_filter::IpFilterLayer. IP allowlist / blocklist middleware — gate routes by client IP.
jobs
Background job queue with a worker pool — async work outside the request lifecycle. In-memory by default; jobs-postgres adds the database-backed queue. See jobs::JobQueue; jobs::Job::run says which context each carries. Background job queue — async work outside the request lifecycle.
jsonapi
JSON:API v1.1 response envelope — wrap a flat serde_json::Value (typical serializer output) in the {"data": {"type", "id", "attributes": {...}}} shape clients expect. See jsonapi::to_resource + jsonapi::to_collection. JSON:API v1.1 response shape adapter.
jti_store
Pluggable JTI revocation / single-use store. The default is in-memory; implement jti_store::JtiStore to back it with Redis or a database when you run more than one instance. Pluggable JTI (JWT ID) revocation / single-use store.
jwt
Standalone HS256 JWT — sign / verify / decode for magic links, microservice tokens, third-party SSO. See jwt::encode + jwt::decode. Minimal JWT (HS256) — sign, verify, decode.
list_params
Shared list-endpoint query-parameter helpers — one place that owns the reserved-key skip list, ?ordering= parsing and ?page_size= clamping, so viewset::handle_list and template_views::ListView cannot drift apart. Query-parameter parsing shared by list endpoints.
livereload
Browser auto-reload — refreshes pages when the server restarts. DEV ONLY — pairs with cargo watch -x run. See livereload. Browser auto-reload — refreshes the page when the server restarts.
logging
One-call tracing-subscriber setup. See logging::setup / logging::Setup. Tracing-subscriber setup in one call.
login_field
[auth] login_field: username or email for tenant sign-in. Which column a tenant user signs in with: [auth] login_field.
login_throttle
Per-IP, per-account and global limits in front of every built-in password login. See login_throttle::LoginThrottle. One gate in front of every built-in password login.
lorem
Lorem ipsum generators — placeholder text for demos, test fixtures and template scaffolds. lorem::words(n), lorem::paragraphs(n), lorem::sentence(). Lorem ipsum placeholder text.
mailable
Laravel-shape Mailable trait — an email type as a struct that owns its template and recipient logic. Pairs with email_templates::EmailRenderer and email_jobs. See mailable::Mailable. The Mailable trait: one email kind, one struct, owning its own template and recipients. It renders with crate::email_templates::EmailRenderer and can be queued through crate::email_jobs.
maintenance
Maintenance-mode middleware — flip a shared flag and new requests get 503 with Retry-After, while requests already running finish. Use it to drain traffic before a deploy or migration. See maintenance::MaintenanceFlag + maintenance::MaintenanceLayer. Maintenance-mode middleware: a shared flag turns every response into a 503 with Retry-After. Use it to drain traffic before a deploy or a migration without cutting off requests already running.
manage
Unified manage runner — one manage::Cli builder in place of src/main.rs + src/bin/manage.rs boilerplate. The tenancy variant appears with the tenancy feature. The manage feature is on by default and pulls in a small axum + tokio surface, so bare-API projects can use the dispatcher without admin. Unified manage runner — collapses src/main.rs + src/bin/manage.rs boilerplate into one builder so apps stop hand-writing the dispatcher.
manage_interactive
Interactive prompts for manage verbs — ask(prompt) reads a line and ask_password(prompt) reads one without echoing. On non-TTY stdin both return Ok(None), so scripted callers still get the “missing required flag” error. Prompts for the manage CLI.
manager
Custom Manager / QuerySet-extension pattern — give a model its own named queries (Post::published()) with a Rust extension trait. See manager for worked examples. How to attach your own query shortcuts to a model, so callers can write Article::objects().published() instead of repeating the same filter everywhere.
mcp
Model Context Protocol (MCP) server — expose tools, prompts and resources to external agents over JSON-RPC 2.0 and Streamable HTTP. Mount with mcp::router (single tenant) or mcp::tenant_router. A Model Context Protocol server, so an outside agent can use your app over JSON-RPC 2.0 and Streamable HTTP.
media
First-class Media model — database-backed file references with direct-browser upload, CDN-aware URLs, soft delete and orphan purge. See media::Media + media::MediaManager. First-class Media model — a real #[derive(Model)] row that references a file in the crate::storage::Storage layer.
messages
Flash messages — messages.success/info/warning/error/debug stored in a signed cookie until the next page renders them. Flash messages, backed by a signed cookie.
method_override
HTTP method override — rewrite POST to PUT/PATCH/DELETE from the X-HTTP-Method-Override header or a _method form field, so HTML forms can drive REST routes. See method_override::MethodOverrideLayer. Method override: turn a POST into PUT, PATCH or DELETE from a hidden form field or a header.
metrics
Prometheus-format metrics — counters + histograms exposed at /metrics. Pure-Rust, no Prometheus client crate. See metrics::MetricsRegistry + metrics::metrics_router. Metrics in the Prometheus text format: counters and histograms, served at /metrics.
migrate
Migrations for rustango.
notifications
Multi-channel notifications — fan one notification out to mail / database / log / broadcast channels. See notifications::notify. Multi-channel notifications — fan one notification out to mail / database / log / broadcast channels.
numberformat
Number formatter — numberformat::format(value, decimal_sep, decimal_pos, grouping, thousand_sep). Thousands grouping, per-locale separators, optional fixed decimal width. Number formatting with explicit separators and grouping.
oauth2
OAuth2 / OIDC social login. Works with plain OAuth2 providers (GitHub, Discord) and OIDC ones (Google, Microsoft, Keycloak) through their /userinfo endpoint. Per-tenant config via oauth2::OAuth2Registry; the optional axum router is oauth2::router (needs admin). OAuth2 / OIDC swiss-knife — one type, every provider.
openapi
OpenAPI 3.1 spec builder + Swagger UI / Redoc viewer routes. Hand-build a spec with openapi::OpenApiSpec and mount it under openapi::router::openapi_router (requires the admin feature). Build an OpenAPI spec, and optionally serve Swagger UI.
pagination
Pagination helpers — RFC 5988 Link headers + cursor params. See pagination::LinkHeaderBuilder. Pagination helpers, in three shapes.
params
Method-adaptive params extractor — params::Params reads the query string on GET/HEAD and the body on QUERY, so one handler serves both. Method-adaptive params extractor: one handler serves GET /x?a=1 and QUERY /x with body a=1.
passkey
Passkey / WebAuthn — credential storage (passkey::WebauthnCredential plus the store API) and the registration / assertion ceremonies, verified in pure Rust (CBOR + ES256). Passkey / WebAuthn support — issue #392.
password_hashers
Pluggable PASSWORD_HASHERS chain with upgrade-on-login. The first password_hashers::PasswordHasher in the list writes new hashes, and every entry verifies its own format. A login that matches an older hasher returns a fresh hash, so you can store the upgrade. Pluggable password-hasher chain with upgrade-on-login.
password_validators
Pluggable AUTH_PASSWORD_VALIDATORS chain — run an ordered list of password_validators::PasswordValidators at signup and password change. Built-ins: MinimumLengthValidator, MaximumLengthValidator, NumericPasswordValidator, UserAttributeSimilarityValidator, CommonPasswordValidator. Pluggable password validator chain.
passwords
Generic password hash/verify + strength heuristic. See passwords::hash. Generic password hashing + strength checking.
permissions
Typed front end for the tenancy::permissions engine — has_perm_for_model::<T> / grant_role_perm_for_model::<T> / model_codenames_for::<T>. Ask for a permission by model type instead of typing the codename string. Needs tenancy, which owns the tables. Permissions, reached by model type.
prelude
use rustango::prelude::*; brings the ORM’s extension traits into scope, so Item::objects().count(&pool) resolves without hunting them down.
problem_details
RFC 7807 “Problem Details for HTTP APIs” — standardized error responses with application/problem+json. Sister to api_errors. See problem_details::ProblemDetails. RFC 7807 “Problem Details for HTTP APIs”: error responses sent as application/problem+json.
prunable
Model pruning — declarative bulk removal of stale rows. See prunable::Prunable + register_prunable!. Model pruning: delete stale rows on a schedule.
query
Query layer for rustango.
random
Random-string helpers — get_random_string, get_random_token_urlsafe. CSPRNG-backed, so they suit session IDs, reset tokens and verification codes. Random strings — get_random_string / get_random_token_urlsafe.
rate_limit
Token-bucket rate limiting middleware — rate_limit::RateLimitLayer. Per-IP, per-header, or global. Returns 429 with Retry-After when exhausted. Token-bucket rate limiting middleware for axum routers.
rate_limit_cache
Cache-backed rate limiting middleware — a fixed-window counter over the cache::Cache trait. Pair it with RedisCache to enforce one limit across several processes. See rate_limit_cache::CacheRateLimitLayer. Distributed rate limiting via the Cache trait.
real_ip
Real-IP extraction for apps behind a trusted reverse proxy. Reads X-Forwarded-For, X-Real-IP, CF-Connecting-IP or RFC 7239 Forwarded and puts the client IP in the request extensions. See real_ip::RealIpLayer. Real-IP extraction middleware for apps behind a trusted reverse proxy.
redirects
Table-driven HTTP redirects. Build a redirects::RedirectMap in code or from a CSV and mount redirects::redirects_middleware. A matching request returns 301/302 with the canonical URL in Location, query string kept. Table-driven HTTP redirects for retired URLs.
request_id
Request ID middleware — assign per-request correlation IDs, honor a trusted proxy’s X-Request-Id for end-to-end propagation. See request_id::RequestIdLayer. Request ID middleware: give every request a unique ID.
request_timeout
Per-request handler timeout — stops a handler that runs too long and returns 504 Gateway Timeout, so a stuck query or external call cannot pile up. Cli::with_settings_from_env() wires it from Settings.server.request_timeout_secs. See request_timeout::RequestTimeoutLayer. Cut off a request that runs too long. The handler is dropped and the client gets 504 Gateway Timeout instead of a hung connection.
scheduler
In-process scheduled task runner — fire async jobs at fixed intervals. See scheduler::Scheduler. In-process scheduled task runner — fire async jobs at fixed intervals.
secrets
Pluggable secrets backend — secrets::Secrets trait + secrets::EnvSecrets
security_headers
Security headers middleware — HSTS / X-Frame-Options / nosniff / Referrer-Policy / Permissions-Policy / CSP. See security_headers::SecurityHeadersLayer. Security headers middleware — HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Cross-Origin-Opener-Policy, and a Content-Security-Policy builder.
serializer
Serializer layer — #[derive(Serializer)] + serializer::ModelSerializer. Typed JSON output from model instances with field control and validation. Serializers — typed JSON built from model instances.
server
The development server. server::Builder owns the boilerplate a tenancy app would otherwise rewrite: DB pool, resolver chain, host dispatch, operator console, bind and serve.
server_timing
Server-Timing header middleware — surface per-request stage durations to the browser DevTools “Network” panel. See server_timing::ServerTimingLayer + server_timing::Timings. Server-Timing header middleware: show per-stage durations in the browser DevTools “Network → Timing” panel.
session
Signed-cookie session primitives — an HMAC-SHA256 key wrapper and a sign(secret, msg) helper, shared by every layer that sets a signed cookie so the crypto lives in one place. See session::SessionSecret. csrf too: its cookie reads session::secure_cookies (#1608). Signed-cookie session primitives: the HMAC-SHA256 key wrapper plus the shared sign and verify helpers.
sessions
Server-side sessions backed by cache::Cache — opaque cookie ID, server-stored bag of typed values, revocable per-session. See sessions::Session + sessions::SessionStore. Server-side session store backed by crate::cache::Cache.
shortcuts
Handler shortcuts — get_object_or_404 / get_list_or_404 / render / redirect. See shortcuts. Handler shortcuts — the helpers every page render needs, so handlers do not reach for status codes, Tera and redirect builders by hand.
shutdown
Graceful-shutdown signal handling — SIGINT and SIGTERM in one place, so no serve path handles only half of them. See shutdown::shutdown_signal. Graceful-shutdown signal handling. Every serve path uses this one function, so they cannot disagree.
signals
Model lifecycle signals — signals::connect_post_save etc. Receivers register globally per model type and run sequentially. Model signals — hooks that run around a row write: pre_save, post_save, pre_delete, post_delete.
signed_url
Signed URL helpers — HMAC-SHA256 with optional expiry. See signed_url::sign / signed_url::verify. Signed URL helpers — tamper-evident URLs with optional expiry.
signing
Value signer — signing::Signer::sign(value) and signing::TimestampSigner with a TTL. Use it for signed payloads such as password reset tokens, magic links and signed cookies. Value signer.
sitemaps
XML sitemap rendering. Write a Sitemap impl (or pass a Vec<SitemapEntry>) and call sitemaps::render_sitemap. For large sites, sitemaps::render_sitemap_index points crawlers at child sitemaps. XML sitemaps.
soft_delete
Soft-delete query helpers — active_filter / trashed_filter / compose_with_active / soft_delete / restore / purge for any model carrying #[rustango(soft_delete)]. See soft_delete. Soft-delete query helpers.
sql
SQL compilation and execution for rustango.
sse
Broadcast event bus — fan-out for SSE / WebSocket / signal-driven push. See sse::EventBus. A broadcast bus that sends one message to every subscriber. Use it for Server-Sent Events and other push patterns.
ssl_redirect
HTTP → HTTPS redirect middleware, with exempt path prefixes and a trusted proxy header. See ssl_redirect::SslRedirectLayer. HTTP to HTTPS redirect middleware, with exempt path prefixes.
sso
SSO (OpenID Connect / social OAuth) login core, independent of the admin. Holds the shared handshake pieces (ResolvedSso, build_provider, verified_email, …) and the DB-backed sso::SsoProvider model. The admin, the tenant console and member auth all build on it; the admin-sso feature adds the admin login wiring. SSO (OpenID Connect / social OAuth) login — the admin-INDEPENDENT sso feature.
static_files
Static file serving — read files from a directory with sensible Content-Type, Cache-Control, Last-Modified, and 304 support. See static_files::StaticFiles + static_files::static_router. Static file serving: read files from a directory and send them with Content-Type, Cache-Control and Last-Modified, and answer 304 to If-Modified-Since.
storage
File storage backends — storage::Storage trait + LocalStorage + InMemoryStorage. File storage: save, read and delete files through one trait, with a backend you choose.
syndication
RSS 2.0 and Atom 1.0 feed rendering. Build a syndication::Feed with channel metadata and syndication::FeedItems, then call syndication::render_rss or syndication::render_atom. RSS 2.0 and Atom 1.0 feeds.
task_context
Context that follows work off the request thread — see task_context::TaskContext. tokio::spawn inherits no task_local!, so deferred work starts with none of its caller’s ambient context unless it is carried deliberately. Context that follows work off the request thread.
template_context_processors
Sitewide template context processors — see template_context_processors. Template context processors.
template_debug
DEBUG template-error overlay — see template_debug. Template error page for development.
template_extensions
Custom template filters and functions — see template_extensions. Custom template filters and functions.
template_views
Generic class-based views for HTML templates — ListView, DetailView, CreateView, UpdateView, DeleteView over #[derive(Model)] schemas, rendered with Tera. The HTML sibling of viewset. Runs on all three backends. See template_views for usage and the Tera context shape. Generic class-based views for HTML templates.
tenancy
Multi-tenancy for rustango.
tenant_log
Ambient tenant identity for log lines — the per-request slot the resolver fills and the access log reads back. Without a resolver the slot stays empty and no tenant is logged. See tenant_log::record / tenant_log::current. Tenant identity for log lines: the field that says whose request this was.
test_assertions
Test assertion helpers — assert_contains / assert_redirects / assert_status / assert_messages over axum responses. The query_counter submodule is ORM instrumentation that sql::executor bumps on every query, so the module is always compiled and the response assertions carry their own _axum gate. Assertion helpers for axum responses.
test_client
Test client — fire HTTP requests against an axum::Router in tests without binding a real socket. See test_client::TestClient. Test client — fire HTTP requests against an axum::Router in tests without binding a real socket.
test_data
Shared test fixtures — the setup_test_data! / setup_test_data_async! macros build the fixture once per process (per file under cargo test, per test under nextest). Shared test fixtures, built once per test process.
test_db
Test-time DB isolation. test_db::with_rollback runs an async closure in a transaction that always rolls back, so one test’s writes never reach the next. Database isolation for tests, in four tiers.
test_factory
Test factories — build model instances for tests without repeating struct literals. A test_factory::Sequence counter plus the test_factory::Factory trait with build_batch. Test fixture builders, in the style of factory_boy.
test_filter
Tag-based test filtering — label a test and run a subset with manage test --tag fast --exclude-tag slow. Put tags!("slow") at the top of a #[test] body and it skips itself when RUSTANGO_TEST_TAGS / RUSTANGO_TEST_EXCLUDE_TAGS filter it out. Run tests by tag — label a test slow or core and filter on it.
test_server
Live HTTP server for tests. Binds an axum::Router to a random localhost port on a background task. Use it when in-process test_client::TestClient routing is not enough, for example with Selenium, websockets, or code that reads the host header. A real HTTP server for tests, on a real port.
test_settings
Test-only Settings overlay — installs a per-task config::Settings overlay, so tests change configuration without touching process-global state. Settings::load / load_from_env return the overlay while it is active. Override Settings for the span of one test.
testkit
Test-support helpers (schema builders from Model::SCHEMA + model factories). Dev-only: #[cfg(test)] for this crate’s own tests, feature = "testkit" for external integration tests. Test-support helpers: build the framework’s own tables from each model’s SCHEMA — never hand-written DDL — and construct fully-populated framework model instances via factories.
text
Text utilities — slugify, html_escape, truncate. Text utilities — slug generation, HTML escaping, truncation.
timesince
Elapsed-time wording — timesince / timeuntil, with a depth control (“4 days, 6 hours”). The Tera filter wrappers live in humanize. Human-readable durations: “4 days, 6 hours”.
totp
TOTP — RFC 6238 time-based one-time passwords for 2FA. See totp::generate / totp::verify / totp::otpauth_url. TOTP — Time-based One-Time Passwords (RFC 6238) for 2FA.
tracing_layer
Per-request tracing span with OpenTelemetry field names and traceparent header propagation. Add tracing_opentelemetry::layer() to your subscriber to get distributed tracing. See tracing_layer::TracingLayer. Per-request tracing span with W3C / OpenTelemetry-conventional field names + traceparent header propagation.
trailing_slash
Trailing-slash redirect middleware — canonicalize URL paths so /posts and /posts/ do not split your traffic. See trailing_slash::TrailingSlashLayer. Trailing-slash redirect middleware: one canonical form per URL.
uploads
Multipart file upload helper — wraps axum’s multipart extractor + the storage::Storage trait. See uploads::save_uploads + uploads::UploadConfig. Multipart file uploads. Joins axum’s multipart extractor to the crate::storage::Storage trait, and handles size limits, extension checks and filename sanitizing for you.
url_codec
URL / IRI / URI helpers — url_encode, uri_to_iri, iri_to_uri, escape_uri_path, filepath_to_uri, urlsafe_base64_encode / _decode and friends. Pure std, so it is always compiled. URL codec helpers: application/x-www-form-urlencoded decoding, RFC 3986 percent encoding, and urlsafe base64.
urls
Named URL reversal — build a URL from a route name and its params, instead of formatting paths by hand. Pair with register_url!. Named URL reversal — build a URL from a route name and its params.
validators
Standalone validators — validate_email, validate_url, validate_slug, validate_min_length / validate_max_length, validate_min_value / validate_max_value. See validators. Standalone validators.
viewset
ModelViewSet — five REST endpoints for any Model table in about five lines. Runs on all three backends, including the .serializer() render extension. See viewset::ViewSet.
webhook
Webhook signature verification (HMAC-SHA256). See webhook::verify_signature. Webhook signature checks, using HMAC and constant-time compare.
webhook_delivery
Outbound webhook delivery — POSTs HMAC-signed JSON through the background job queue, so retries with backoff come for free. See webhook_delivery::WebhookSubscription. Outbound webhooks: POST an HMAC-signed JSON payload to a subscriber URL through the background job queue.
welcome
First-run welcome page — confidence signal that rustango is wired up. Mount under / while bootstrapping; replace once you have content. See welcome::welcome_router. First-run welcome page. It shows that rustango is wired up.
ws
WebSocket handler scaffold — fan-out via sse::EventBus with auto JSON encode/decode + keep-alive ping. See ws::WsHub + ws::ws_handler. WebSocket handler built on the SSE EventBus.

Macros§

Q
Q!() — compact filter syntax compile-time-resolved against typed columns. Each invocation expands to the equivalent typed-column method call, so field-name typos fail the build. See rustango_macros::Q for the supported lookup suffixes.
atomic
Sugar over atomic that wraps the body in Box::pin(async move { … }) so callers don’t have to. Identical semantics:
by_dialect
Pick a value per backend, with every backend spelled out.
embed_migrations
Bake every migration file in a directory into the binary at compile time, for shipping a single-binary distribution. Pair with migrate::migrate_embedded.
register_admin_computed
Register an admin computed field. Pair with a #[derive(Model)] type whose admin(list_display = "…") names this field.
register_admin_inline
Register an admin inline. The parent / child arguments must match the ModelSchema::table of two #[derive(Model)] types already in the registry.
register_admin_inline_generic
Register a generic admin inline. Same shape as register_admin_inline! but takes ct + pk instead of fk.
register_admin_list_filter
Register a custom list filter on the table whose list view should show the filter card.
register_admin_object_permission
Register a permission predicate for one model.
register_admin_queryset
Register an admin queryset hook for one model.
register_admin_superuser_fields
Mark fields of one model superuser-only for an admin write. The model, action and field names are checked at compile time, so call it where the fields are visible.
register_admin_view
Register a custom admin view for one model.
register_command
Register a manage command from any crate, without the host app changing main. The handler gets a CommandContext and the arguments after the verb (--tenant <slug> already taken out). A name that clashes with a built-in verb or another command makes Cli::run fail at startup.
register_mcp_resource
Register a resource that every authenticated agent can read, with no skill grant needed.
register_mcp_tool
Register a tool at compile time.
register_migration_callback
Register a named migration callback. Pair the chosen name with a {"callback": {"name": "..."}} entry in your migration JSON’s forward array.
register_prunable
Register a Prunable impl so manage prune, prune_all and prune_pretend can find it. Pass the model type only; the name comes from its table.
register_template_context_processor
Register a context processor. apply_to_context runs it.
register_template_filter
Register a Tera filter. apply_to_tera installs it.
register_template_function
Register a Tera function. apply_to_tera installs it.
register_url
Register a named URL pattern at startup. Uses rustango::inventory, so you do not need your own dependency on it.
setup_test_data
A shared fixture built by sync code. Wraps a std::sync::OnceLock.
setup_test_data_async
A shared fixture built by async code, such as one that inserts rows. Wraps a tokio::sync::OnceCell, so concurrent first callers all wait on one run of the body.
tags
Declare this test’s tags and return early if the env vars filter it out. Put it at the top of the test body, before any setup.
tri_dialect_test
Fan a list of scenario functions out into one #[tokio::test] per backend.
with_rollback
with_rollback with the Box::pin(async move { … }) wrapper written for you. Behaves the same:
with_truncate_after
with_truncate_after in the same macro shape as with_rollback!:

Enums§

RustangoError
One error type for app code. Every framework error has a From impl into it, so ? works in a handler.

Functions§

server_error
A logged 500 that withholds the cause, for handlers that return (StatusCode, String): .map_err(rustango::server_error)? (#2032).

Type Aliases§

RustangoResult
Result with RustangoError as the error type.

Attribute Macros§

main
#[rustango::main] — the application entrypoint. Wraps #[tokio::main] and boots tracing-subscriber from RUST_LOG, falling back to info,sqlx=warn. RUSTANGO__LOGGING__FORMAT=json logs JSON. #[rustango::main] — the runserver entrypoint. Wraps #[tokio::main] and a default tracing_subscriber initialisation (env-filter, falling back to info,sqlx=warn) so user main functions are zero-boilerplate. RUST_LOG and RUSTANGO__LOGGING__FORMAT (e.g. json) come from the real environment, else from ./.env (only those keys are read):

Derive Macros§

Form
#[derive(Form)] — implements forms::Form so a struct can be parsed from an HTTP form payload with multi-error validation. Re-exported only when the forms feature is on. Derive rustango::forms::Form (slice 8.4B). Generates a parse(&HashMap<String, String>) -> Result<Self, FormErrors> impl that walks every named field and:
Model
#[derive(Model)] — populates the inventory registry the admin walks, generates objects() / typed columns / insert / delete / save.
Serializer
#[derive(Serializer)] — implements serializer::ModelSerializer on a struct, generating from_model, a custom serde::Serialize (respecting write_only), and writable_fields. Re-exported when the serializer feature is on. Derive rustango::serializer::ModelSerializer for a struct. (intra-doc link disabled — the macro crate doesn’t depend on rustango itself, so rustdoc can’t resolve the path.)
ViewSet
#[derive(ViewSet)] — generates a router(prefix, pool) -> axum::Router associated method on a marker struct, wiring the full CRUD ViewSet in one annotation. Re-exported under admin or tenancy (the generated router(...) expands to __axum::Router, which admin provides); the generated router(...) works without tenancy, and tenant_router(...) adds the multi-tenant path when tenancy is also enabled. Derive a router(prefix, pool) -> axum::Router associated method on a marker struct, wiring the full CRUD ViewSet in one annotation.