Project: Blog API
A complete CRUD API.
Learning Objectives
- Build a CRUD app
##Project: Blog API
Building a Blog API is the perfect capstone project to solidify your Actix Web knowledge. A Blog API involves CRUD (Create, Read, Update, Delete) operations, database integration, data validation, and potentially authentication.
#API Design
A standard Blog API might look like this:
GET /posts- List all postsPOST /posts- Create a new postGET /posts/{id}- Get a specific postPUT /posts/{id}- Update a postDELETE /posts/{id}- Delete a post
#Defining the Models
You'll need models for your database entities and DTOs (Data Transfer Objects) for your API requests/responses.
use serde::{Serialize, Deserialize};
// What we return to the client
#[derive(Serialize)]
pub struct Post {
pub id: i32,
pub title: String,
pub body: String,
pub published: bool,
}
// What the client sends to create a post
#[derive(Deserialize)]
pub struct CreatePostReq {
pub title: String,
pub body: String,
}#Implementing CRUD Handlers
Here is an example of the create_post handler using SQLx:
use actix_web::{post, web, HttpResponse, Responder};
use sqlx::PgPool;
#[post("/posts")]
async fn create_post(
req: web::Json<CreatePostReq>,
db: web::Data<PgPool>
) -> impl Responder {
let result = sqlx::query_as!(
Post,
"INSERT INTO posts (title, body, published) VALUES ($1, $2, false) RETURNING id, title, body, published",
req.title,
req.body
)
.fetch_one(db.get_ref())
.await;
match result {
Ok(post) => HttpResponse::Created().json(post),
Err(_) => HttpResponse::InternalServerError().finish(),
}
}#Structuring the Application
As your API grows, you shouldn't put all handlers in main.rs. A common pattern is to split the app into modules:
src/
main.rs # Setup and HttpServer
models.rs # Structs and DTOs
handlers.rs # Actix Web routes
db.rs # Database query logicYou can then use web::scope to group routes together:
// in main.rs
App::new()
.app_data(db_pool.clone())
.service(
web::scope("/api/v1")
.service(handlers::get_posts)
.service(handlers::create_post)
)This project prepares you for building scalable, real-world web services in Rust!
Practical Exercise
Implement the Blog API
TaskRequirements
Try solving the exercise in your local environment first. Once you have a solution, or if you get completely stuck, reveal the answer.
Key Takeaways
- Design clear RESTful routes (`GET`, `POST`, `PUT`, `DELETE`).
- Separate your database entities from your request DTOs (`Deserialize`).
- Use `web::scope` to group endpoints under a common prefix like `/api/v1`.
- Move handlers and models into separate files (`handlers.rs`, `models.rs`) for maintainability.
Finished reading?
Mark this lesson as done to track your progress and earn XP.