This directory contains the Rust backend for Agora. The API is built with Axum, uses SQLx for database access and migrations, and stores data in PostgreSQL.
Axum is the HTTP framework used to define routes, attach middleware layers, manage shared application state, and return typed JSON responses.
SQLx is used for PostgreSQL connectivity, running migrations, and mapping rows into Rust structs. In this codebase, the server creates a PgPool at startup and shares it with route handlers through Axum state.
PostgreSQL is the backing database for Agora. The local development database is provided by docker-compose.yml, and the schema is created from the SQL files in migrations/.
- Rust stable toolchain
- Cargo
- Docker Desktop or a local PostgreSQL instance
sqlx-cli
Install sqlx-cli with PostgreSQL support:
cargo install sqlx-cli --no-default-features --features postgresThese variables are read from .env at startup:
| Variable | Required | Default | Purpose |
|---|---|---|---|
DATABASE_URL |
Yes | None | PostgreSQL connection string used by the server and SQLx migrations |
PORT |
No | 3001 |
Port the Axum server binds to |
RUST_ENV |
No | development |
Enables production-specific behavior such as HSTS when set to production |
RUST_LOG |
No | info |
Log level for tracing output |
CORS_ALLOWED_ORIGINS |
No | http://localhost:3000,http://localhost:5173 |
Comma-separated allowlist for browser clients |
SOROBAN_RPC_URL |
No | https://soroban-testnet.stellar.org |
Soroban RPC endpoint used by blockchain connectivity health checks |
Example values are already provided in server/.env.example.
Run all commands from the server/ directory.
cp .env.example .envIf you are on PowerShell, use:
Copy-Item .env.example .envThe default local database URL is:
postgres://user:password@localhost:5432/agora
docker compose up -dThis starts a local PostgreSQL container with:
- Host:
localhost - Port:
5432 - Database:
agora - Username:
user - Password:
password
sqlx migrate runThe migration files live in server/migrations/ and create the initial schema for users, organizers, events, ticket tiers, tickets, and transactions.
cargo runOn success, the API will start on http://localhost:3001 unless you override PORT.
Try the health endpoint:
curl http://localhost:3001/api/v1/healthTry the blockchain health endpoint:
curl http://localhost:3001/api/v1/health/blockchainThe backend follows a straightforward layered Axum structure:
Request
-> Layer
-> Route
-> Handler
-> Model / Database
-> Response
src/
|- main.rs # Startup: load env, init logging, connect DB, run migrations, serve app
|- lib.rs # Module exports
|- config/ # Middleware and environment configuration
|- routes/ # Router assembly and endpoint registration
|- handlers/ # HTTP handlers and request/response orchestration
|- models/ # SQLx-backed Rust structs representing database entities
`- utils/ # Shared response, error, logging, and test helpers
main.rsloads.env, initializes logging, reads config, connects to PostgreSQL, and runs embedded SQLx migrations.src/routes/mod.rsbuilds the Axum router and applies shared middleware layers.- Incoming requests pass through middleware from
src/config/:- request ID generation and propagation
- CORS configuration
- security headers
- The matched route forwards control to a handler in
src/handlers/. - The handler uses shared state such as the
PgPool, performs validation or queries, and builds a response. - Model structs in
src/models/define the Rust shape of database records and are the right place for table-backed types. - Shared helpers in
src/utils/response.rsandsrc/utils/error.rskeep API responses consistent.
When adding a new API feature, use this flow:
- Add or update the database schema in
migrations/if the feature needs persistence. - Add or update a model in
src/models/if the endpoint returns or stores a table-backed entity. - Create a handler in
src/handlers/for the request logic. - Register the route in
src/routes/mod.rs. - Reuse helpers in
src/utils/for standard success and error responses.
For example, a new organizer endpoint would typically mean:
- adding
handlers/organizers.rs - exporting that module from
handlers/mod.rs - wiring routes in
routes/mod.rs - using models from
models/organizer.rs
Start the server first, then run:
bash ./test_health_endpoints.shIf you are using Git Bash on Windows, run the same command there. The script checks:
GET /api/v1/healthGET /api/v1/health/blockchainGET /api/v1/health/dbGET /api/v1/health/ready
Run the full test suite with:
cargo testOn Windows, if your default Rust toolchain is GNU and you hit a dlltool.exe error, use the installed MSVC toolchain instead:
cargo +stable-x86_64-pc-windows-msvc testUseful additional checks:
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warningsWhen you open your PR for this task, include:
Closes #issue_number