This repository contains an application template built using Axum and PostgreSQL. It serves as a starting point for creating a new Axum server.
Inspired by Zero To Production In Rust and realworld-axum-sqlx.
The full list of crates used can be found in the Cargo.toml file. However, here are some key ones:
- Axum - A user-friendly, modular web framework built with Tokio, Tower, and Hyper.
- Sqlx - An asynchronous, pure Rust SQL crate that supports compile-time checked queries without a DSL. It supports PostgreSQL, MySQL, SQLite, and MSSQL.
- Tracing - A framework for instrumenting Rust programs to collect structured, event-based diagnostic information.
- Chrono - A comprehensive Date and Time library for Rust.
- Serde - A framework for efficiently and generically serializing and deserializing Rust data structures.
- Uuid - A library for generating and parsing UUIDs.
To begin with this project:
SQLx offers a command-line tool for creating and managing databases as well as migrations. It is available on the Cargo crates registry as sqlx-cli
and can be installed as follows:
$ cargo install sqlx-cli --features postgres
The most straightforward way to run Postgres is by using a container with a pre-built image. The command below will start latest version of Postgres using Docker:
$ docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=password postgres
$ git clone https://github.com/koskeller/axum-postgres-template
$ cd axum-postgres-template
The backend application is preferably configured via environment variables. To simplify the process during development, we can use .env
files to avoid defining the variables each time. As a starting point, you can simply copy the sample .env
file in this repo and modify the .env
file as per the comments therein.
$ cp .env.sample .env
With sqlx-cli
installed and your .env
file set up, you only need to run the following command to prepare the Postgres database for use:
$ sqlx db setup
To avoid the need of having a development database around to compile the project even when no modifications (to the database-accessing parts of the code) are done, this projects enables "offline mode" to cache the results of the SQL query analysis using the sqlx command-line tool. See sqlx-cli/README.md for more details.
$ cargo sqlx prepare
With everything else set up, all you need to do now is:
$ cargo run
To start the server and autoreload on code changes:
$ cargo install cargo-watch
$ cargo watch -q -x run
To format .json
logs using jq
:
$ cargo watch -q -x run | jq .
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ExampleReq {
pub input: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ExampleResp {
pub output: String,
}
pub async fn example(
State(state): State<AppState>,
req: Result<Json<ExampleReq>, JsonRejection>,
) -> Result<Json<ExampleResp>, ApiError> {
// Returns ApiError::InvalidJsonBody if the Axum built-in extractor
// returns an error.
let Json(req) = req?;
// Proceed with additional validation.
if req.input.is_empty() {
return Err(ApiError::InvalidRequest(
"'input' should not be empty".to_string(),
));
}
// Anyhow errors are by default converted into ApiError::InternalError and assigned a 500 HTTP status code.
let data: anyhow::Result<()> = Err(anyhow!("Some internal error"));
let data = data?;
let resp = ExampleResp {
output: "hello".to_string(),
};
Ok(Json(resp))
}
Contributions are always welcome! Feel free to check the current issues in this repository for tasks that need attention. If you find something missing or that could be improved, please open a new issue.