Small Rust URL shortener service built with Axum + SQLite.
It supports:
- HTML form (
/) and JSON API (/api/shorten) for creating short links - Redirects via
/{slug} - SQLite migrations and file-backed DB tuning (WAL + busy timeout)
- In-memory rate limiting (per client/IP)
- Health and Prometheus-style metrics endpoints
- Buffered asynchronous hit-count persistence for redirects
- Tests and Criterion benchmarks for SQLite contention / hit-count buffering
cargo runDefaults:
- App:
http://localhost:3000 - DB:
sqlite://data/shortener.db?mode=rwc
docker compose up --buildGET /- simple HTML form UIPOST /shorten- form submitPOST /api/shorten- JSON API ({"url":"https://example.com"})GET /{slug}- 302 redirectGET /health- health check JSONGET /metrics- Prometheus text metrics
curl -s http://localhost:3000/api/shorten \
-H 'content-type: application/json' \
-d '{"url":"https://example.com"}'Common vars (see src/config.rs):
HOST(default0.0.0.0)PORT(default3000)BASE_URL(defaulthttp://localhost:<PORT>)DATABASE_URL(defaultsqlite://data/shortener.db?mode=rwc)RATE_LIMIT_RPS/RATE_LIMIT_BURSTTRUST_PROXY_HEADERS(usex-forwarded-forfor client identity)SQLITE_BUSY_TIMEOUT_MS
Hit-count writer tuning:
HIT_COUNT_QUEUE_SIZEHIT_COUNT_OVERFLOW_MAX_EVENTSHIT_COUNT_FLUSH_INTERVAL_MSHIT_COUNT_MAX_BATCH_EVENTSHIT_COUNT_ENQUEUE_TIMEOUT_MS
src/main.rs- binary entrypointsrc/lib.rs- crate wiring and public exportssrc/app.rs- app startup, router, middleware, graceful shutdownsrc/handlers.rs- HTTP handlers (UI/API/redirect/health/metrics)src/service.rs- URL normalization, slug generation, DB service logicsrc/db.rs- SQLite pool setup, migrations, WAL/busy-timeout tuningsrc/hit_counter.rs- buffered async hit-count queue + workersrc/metrics.rs- in-memory counters/histogram + Prometheus renderingsrc/rate_limiter.rs- in-memory token-bucket limitersrc/views.rs- HTML rendering for the home formsrc/models.rs- API DTOs and DB row conversionsrc/tests.rs- integration-style tests (Axum router + SQLite)migrations/0001_create_links.sql- schema forlinksbenches/sqlite_busy.rs- SQLite busy/lock contention benchmarkbenches/hit_count_buffered.rs- redirect hit-count buffering benchmarkDockerfile/compose.yaml- containerized local run
cargo test
cargo bench
cargo check
cargo clippy --all-targets --all-features -- -D warnings