Skip to main content

Task 1: Organize the project structure and set up the /healthcheck endpoint

Before diving in, first we'll setup some conventions for organizing the code, which will help us maintain a clean and scalable project structure, benefits of the Rust module system.

The router will live inside the src/routes module, and each endpoint will have its own module. This way, we can keep the codebase organized and easy to navigate.

To do so, we'll update the directory structure as such:

upb-rust-workshop/
├─ src/
│ ├─ routes/
│ │ └─ mod.rs
│ └─ main.rs # Entry point
├─ target/ # Build artifacts
├─ .gitignore # Git ignore file
├─ Cargo.lock # Dependency lock file
└─ Cargo.toml # Project manifest

Within src/routes/mod.rs, we'll move the router initialization from main.rs as follows:

src/routes/mod.rs
use axum::Router;

pub fn app() -> Router {
Router::new().route("/", get(async || "Hello, World!"))
}

After that, the main.rs will become:

src/main.rs
pub mod routes;

use axum;

#[tokio::main]
async fn main() {
let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap();
println!(
"Server running on http://{}",
listener.local_addr().unwrap()
);
axum::serve(listener, routes::app()).await.unwrap();
}

If you run the server now, you should see the message Server running on http://0.0.0.0:8080, and the / endpoint should return Hello, World!.

Now, let's add a /healthcheck endpoint to our server. This endpoint will be used to check if the server is running and healthy.

To do so, create a new module src/routes/healthcheck.rs and add the following code:

src/routes/healthcheck.rs
use axum::{Router, http::StatusCode, response::IntoResponse, routing::get};

pub fn register() -> Router {
Router::new().route("/", get(health_check))
}

async fn health_check() -> impl IntoResponse {
todo!("Implement the health check endpoint")
}

Next, update src/routes/mod.rs to include the new module:

src/routes/mod.rs
use axum::Router;

mod healthcheck;

pub fn app() -> Router {
Router::new().nest("/healthcheck", healthcheck::register())
}

Why we did that? By nesting the /healthcheck route inside the main router, we can easily add more routes in the future without cluttering the main router.

Your Task​

As task, implement the health_check function to return a 200 OK status code with the message Server is running.

Conclusion​

In this task, we've organized the project structure and added a /healthcheck endpoint to our server. This will help us maintain a clean and scalable codebase as we add more features to our web server.