Feature flags
zapline follows "pay only for what you use": anything that pulls in a dependency sits behind a Cargo feature, and a feature you don't use adds no code to your binary and no work to a request.
[dependencies]
zapline = "0.1" # the default features
zapline = { version = "0.1", features = ["ws", "fs"] } # default features plus WebSockets and static files
zapline = { version = "0.1", features = ["full"] } # everything
zapline = { version = "0.1", default-features = false, features = ["json", "macros"] } # a minimal build
Or let the CLI edit Cargo.toml:
zapline add ws fs # Added features: ws, fs
zapline add --list # every feature, one line each; * marks the ones you have
When code uses something behind a feature that is off, zapline check and zapline test say which one to add: hint: enable the `ws` feature: zapline add ws (details).
Every feature
The default features are macros, json, query, form, openapi, validate, config and tracing. The full feature enables the defaults plus everything else.
| Feature | Default | Enables | Implies | Dependencies it adds |
|---|---|---|---|---|
macros | yes | The route attribute macros #[get], #[post], #[put], #[patch], #[delete], #[head], #[options] and #[route], with their OpenAPI arguments (Routing, OpenAPI) | zapline-macros (syn, quote, proc-macro2) | |
json | yes | Json<T> as an extractor and a response, structured error details, Ndjson, Sse::json_data, Message::json and Field::json for WebSockets and uploads, and the test client's .json() | serde_json | |
query | yes | The Query<T> extractor | serde_urlencoded | |
form | yes | The Form<T> extractor and the test client's .form() | serde_urlencoded | |
openapi | yes | zapline::openapi: the OpenApi plugin, Swagger UI, Scalar and Redoc, the builder methods, JsonSchema, and typed clients (client_js, codegen) (OpenAPI, Typed frontends) | json | schemars, zapline-codegen |
validate | yes | zapline::validate: Valid<T> and the 422 error format (Validation) | json | validator (with derive) |
config | yes | zapline::config: Config, Secret<T> and App::config (Configuration) | toml | |
tracing | yes | zapline::telemetry: Telemetry, init() and Trace (Observability). With it, framework logs (failed requests, panics, jobs) go through tracing; without it they go to stderr. | tracing, tracing-subscriber (env-filter, fmt, json) | |
http2 | full | HTTP/2 support on the server (Server) | hyper/http2, hyper-util (http2, server-auto) | |
tls | full | zapline::tls: TLS with rustls (Server) | tokio-rustls (ring, tls12) | |
http3 | Experimental. zapline::http3: HTTP/3 over QUIC next to HTTPS, advertised with Alt-Svc (Server) | tls | quinn (rustls-ring), h3, h3-quinn | |
ws | full | zapline::ws: WebSockets (WebSockets) | tokio-tungstenite (handshake) | |
fs | full | zapline::fs: ServeDir, ServeFile and App::static_files (Static files) | mime_guess, tokio-util (io) | |
multipart | full | zapline::multipart: the Multipart extractor (Uploads) | multer | |
compression | full | middleware::Compression and CompressionLevel (Hardening) | async-compression (gzip, brotli, zstd, deflate, zlib), tokio-util | |
jwt | full | JSON Web Tokens: JwtConfig, Claims, Jwt<C>, JwtAuthenticator, Authenticate::jwt() and App::jwt; key rings with JwtKey (rotate, retire) and App::serve_jwks (Authentication) | json | jsonwebtoken (aws-lc backend, PEM keys) |
jwks | full | Jwks: verify tokens with an identity provider's JWK Set, cached with a TTL, refreshed on unknown kid (rate limited), stale keys kept on errors, OpenID discovery (JWKS) | jwt | hyper-rustls (hyper client, rustls) |
cookies | full | zapline::cookies (CookieJar, signed and private jars, Key), zapline::session (SessionLayer, Session) and auth::{Csrf, CsrfToken} (Cookies, sessions & CSRF) | json | cookie (percent-encode, signed, private), getrandom, hmac, sha2 (signed CSRF tokens) |
views | full | zapline::view: Views, App::views, HxRequest, Hx (Views & htmx) | minijinja (loader) | |
password | full | zapline::auth::password: Argon2id hash and verify (Authentication) | argon2, getrandom | |
mail | full | zapline::mail: Mailer, Email, the dev inbox (Email) | lettre (SMTP, rustls) | |
oauth | full | zapline::auth::oauth: OAuth (GitHub, Google, custom), App::oauth, OAuthLogin (Social login) | json | hyper-rustls (hyper client, rustls), sha2, getrandom |
i18n | full | zapline::i18n: I18n (TOML files per language), App::i18n, the Locale extractor, plurals, t(...) in templates (Translations) | toml | |
redis | full | zapline::redis: a built-in Redis client (Redis, App::redis), Cache::redis, Live::redis, RateLimit::redis, RedisStore for sessions (Running several instances) | json | |
redis-tls | full | rediss:// URLs for the Redis client: TLS with rustls, the Mozilla root store or your own CA (?ca_file=, Redis::with_ca_pem), and an SNI override (?sni=) (Running several instances) | redis | tokio-rustls, webpki-roots |
otlp | full | OpenTelemetry trace export over OTLP/HTTP: Telemetry::otlp, or just OTEL_EXPORTER_OTLP_ENDPOINT (Observability) | tracing, json | hyper-rustls (hyper client, rustls) |
tz | full | IANA time zones (CRON_TZ=Europe/Paris) in cron schedules. UTC and fixed offsets work without it. | jiff (system tz database; bundled on Windows) | |
storage | full | zapline::storage: Storage (local directory, memory), signed links, App::storage (File storage) | mime_guess, hmac, sha2, getrandom | |
s3 | Storage::s3 and S3: S3, R2, MinIO and other S3-compatible services (File storage) | storage | hyper-rustls (hyper client, rustls) | |
cache | full | zapline::cache: Cache (get_or_set without stampedes), ResponseCache, ETag (Caching) | json | |
postgres | zapline::db for Postgres: Database, Db, DbCheck, migrations (Databases) | sqlx (postgres, runtime-tokio, migrate, rustls) | ||
sqlite | zapline::db for SQLite, including Database::sqlite_memory() for tests (Databases) | sqlx (sqlite, runtime-tokio, migrate) | ||
chrono | full | zapline::chrono (NaiveDate, DateTime<Utc>) with sqlx, serde and OpenAPI support; extract::datetime for datetime-local inputs (Databases) | chrono | |
uuid | full | zapline::uuid::Uuid with sqlx, serde and OpenAPI support (Databases) | uuid |
With postgres or sqlite (and json), zapline::jobs adds durable jobs stored in the same database. With postgres or sqlite, App::admin adds an admin panel for every table.
| full | | Every feature above except the database backends (pick postgres and/or sqlite) | all | |
openapi, validate, jwt and cookies turn on json as well, because their error bodies, schemas and session data are JSON.
Always included
Some modules have no feature flag because they add no dependencies:
| Module | What it provides |
|---|---|
| Core | Routing, Path, State, Extension, Bytes and String extractors, responses, errors, the test client, startup/shutdown hooks and plugins |
middleware | Logger, Cors, Timeout, DefaultHeaders, CatchPanic, ConcurrencyLimit, NormalizePath, RateLimit, SetRequestId, SecurityHeaders |
auth | BearerToken, BasicAuth, ApiKey, Authenticate, Guard, route policies (JWT and CSRF need their own features) |
di | Dep<T>, Cached<T>, Inject and the provide* methods |
tasks | BackgroundTasks, App::schedule, App::background |
sse, stream | Server-Sent Events, StreamBody and BodyStream (Ndjson needs json) |
metrics, health | The Prometheus Metrics plugin and the Health plugin |
Choosing features
- A typical JSON API: the defaults. Add
jwtandcompressionwhen you need them. - A web app with server-rendered pages:
cookies(sessions, CSRF) andfs(assets), plusmultipartfor uploads. - Realtime features:
ws. Server-Sent Events need no feature. - A slim microservice:
default-features = false, features = ["json", "macros"]and addconfigortracingif you use them. Types and macros behind a missing feature are not compiled, so the compiler tells you when you reach for one, andzapline checknames the feature to add. - Everything while exploring:
full. The examples in the repository (cargo run -p zapline-examples --example openapi) are built with it.
Features are additive and unify across your dependency tree, so one crate enabling full enables it for all. The same applies to the macros: #[get(..)] works without openapi, it just doesn't document anything.
Put #[model] on request and response types and zapline is the only dependency you need: it derives Serialize, Deserialize, JsonSchema (with openapi) and Validate (with validate) through zapline's own re-exports. Writing the derives yourself still works; then add the crates they expand to:
serde = { version = "1", features = ["derive"] } # #[derive(Serialize, Deserialize)]
schemars = "1" # #[derive(JsonSchema)]
validator = { version = "0.21", features = ["derive"] } # #[derive(Validate)]
tokio = { version = "1", features = ["macros", "rt"] } # #[tokio::test], in [dev-dependencies]
cargo doc -p zapline --all-features --open builds the API reference with every module visible. The reference on docs.rs is built the same way.